johnkim05_obsidian-uuugl-pl.../main.js
john 77871525b1 📱 v1.4.0: Add iOS & Android Mobile Support
## Cross-Platform Implementation

### Changes
- manifest.json: `isDesktopOnly: false` for mobile compatibility
- main.js: Rebuilt with mobile authentication support

### Authentication Flow
- Browser-based OAuth with obsidian:// callback
- Works on Desktop (Electron) and Mobile (iOS/Android)
- Single codebase for all platforms

### Compatibility
-  PC (Windows/Mac/Linux): No changes, works as before
-  Mobile (iOS/Android): Now fully supported

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 22:17:01 +09:00

22508 lines
3.3 MiB

"use strict";
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 __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name6 in all)
__defProp(target, name6, { get: all[name6], 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);
// node_modules/@firebase/util/dist/postinstall.mjs
var getDefaultsFromPostinstall;
var init_postinstall = __esm({
"node_modules/@firebase/util/dist/postinstall.mjs"() {
getDefaultsFromPostinstall = () => void 0;
}
});
// node_modules/@firebase/util/dist/node-esm/index.node.esm.js
function getGlobal() {
if (typeof self !== "undefined") {
return self;
}
if (typeof window !== "undefined") {
return window;
}
if (typeof global !== "undefined") {
return global;
}
throw new Error("Unable to locate global object.");
}
function isCloudWorkstation(url) {
try {
const host = url.startsWith("http://") || url.startsWith("https://") ? new URL(url).hostname : url;
return host.endsWith(".cloudworkstations.dev");
} catch {
return false;
}
}
async function pingServer(endpoint) {
const result = await fetch(endpoint, {
credentials: "include"
});
return result.ok;
}
function createMockUserToken(token, projectId) {
if (token.uid) {
throw new Error('The "uid" field is no longer supported by mockUserToken. Please use "sub" instead for Firebase Auth User ID.');
}
const header = {
alg: "none",
type: "JWT"
};
const project = projectId || "demo-project";
const iat = token.iat || 0;
const sub = token.sub || token.user_id;
if (!sub) {
throw new Error("mockUserToken must contain 'sub' or 'user_id' field!");
}
const payload = {
// Set all required fields to decent defaults
iss: `https://securetoken.google.com/${project}`,
aud: project,
iat,
exp: iat + 3600,
auth_time: iat,
sub,
user_id: sub,
firebase: {
sign_in_provider: "custom",
identities: {}
},
// Override with user options
...token
};
const signature = "";
return [
base64urlEncodeWithoutPadding(JSON.stringify(header)),
base64urlEncodeWithoutPadding(JSON.stringify(payload)),
signature
].join(".");
}
function getEmulatorSummary() {
const summary = {
prod: [],
emulator: []
};
for (const key of Object.keys(emulatorStatus)) {
if (emulatorStatus[key]) {
summary.emulator.push(key);
} else {
summary.prod.push(key);
}
}
return summary;
}
function getOrCreateEl(id) {
let parentDiv = document.getElementById(id);
let created = false;
if (!parentDiv) {
parentDiv = document.createElement("div");
parentDiv.setAttribute("id", id);
created = true;
}
return { created, element: parentDiv };
}
function updateEmulatorBanner(name6, isRunningEmulator) {
if (typeof window === "undefined" || typeof document === "undefined" || !isCloudWorkstation(window.location.host) || emulatorStatus[name6] === isRunningEmulator || emulatorStatus[name6] || // If already set to use emulator, can't go back to prod.
previouslyDismissed) {
return;
}
emulatorStatus[name6] = isRunningEmulator;
function prefixedId(id) {
return `__firebase__banner__${id}`;
}
const bannerId = "__firebase__banner";
const summary = getEmulatorSummary();
const showError = summary.prod.length > 0;
function tearDown() {
const element = document.getElementById(bannerId);
if (element) {
element.remove();
}
}
function setupBannerStyles(bannerEl) {
bannerEl.style.display = "flex";
bannerEl.style.background = "#7faaf0";
bannerEl.style.position = "fixed";
bannerEl.style.bottom = "5px";
bannerEl.style.left = "5px";
bannerEl.style.padding = ".5em";
bannerEl.style.borderRadius = "5px";
bannerEl.style.alignItems = "center";
}
function setupIconStyles(prependIcon, iconId) {
prependIcon.setAttribute("width", "24");
prependIcon.setAttribute("id", iconId);
prependIcon.setAttribute("height", "24");
prependIcon.setAttribute("viewBox", "0 0 24 24");
prependIcon.setAttribute("fill", "none");
prependIcon.style.marginLeft = "-6px";
}
function setupCloseBtn() {
const closeBtn = document.createElement("span");
closeBtn.style.cursor = "pointer";
closeBtn.style.marginLeft = "16px";
closeBtn.style.fontSize = "24px";
closeBtn.innerHTML = " &times;";
closeBtn.onclick = () => {
previouslyDismissed = true;
tearDown();
};
return closeBtn;
}
function setupLinkStyles(learnMoreLink, learnMoreId) {
learnMoreLink.setAttribute("id", learnMoreId);
learnMoreLink.innerText = "Learn more";
learnMoreLink.href = "https://firebase.google.com/docs/studio/preview-apps#preview-backend";
learnMoreLink.setAttribute("target", "__blank");
learnMoreLink.style.paddingLeft = "5px";
learnMoreLink.style.textDecoration = "underline";
}
function setupDom() {
const banner = getOrCreateEl(bannerId);
const firebaseTextId = prefixedId("text");
const firebaseText = document.getElementById(firebaseTextId) || document.createElement("span");
const learnMoreId = prefixedId("learnmore");
const learnMoreLink = document.getElementById(learnMoreId) || document.createElement("a");
const prependIconId = prefixedId("preprendIcon");
const prependIcon = document.getElementById(prependIconId) || document.createElementNS("http://www.w3.org/2000/svg", "svg");
if (banner.created) {
const bannerEl = banner.element;
setupBannerStyles(bannerEl);
setupLinkStyles(learnMoreLink, learnMoreId);
const closeBtn = setupCloseBtn();
setupIconStyles(prependIcon, prependIconId);
bannerEl.append(prependIcon, firebaseText, learnMoreLink, closeBtn);
document.body.appendChild(bannerEl);
}
if (showError) {
firebaseText.innerText = `Preview backend disconnected.`;
prependIcon.innerHTML = `<g clip-path="url(#clip0_6013_33858)">
<path d="M4.8 17.6L12 5.6L19.2 17.6H4.8ZM6.91667 16.4H17.0833L12 7.93333L6.91667 16.4ZM12 15.6C12.1667 15.6 12.3056 15.5444 12.4167 15.4333C12.5389 15.3111 12.6 15.1667 12.6 15C12.6 14.8333 12.5389 14.6944 12.4167 14.5833C12.3056 14.4611 12.1667 14.4 12 14.4C11.8333 14.4 11.6889 14.4611 11.5667 14.5833C11.4556 14.6944 11.4 14.8333 11.4 15C11.4 15.1667 11.4556 15.3111 11.5667 15.4333C11.6889 15.5444 11.8333 15.6 12 15.6ZM11.4 13.6H12.6V10.4H11.4V13.6Z" fill="#212121"/>
</g>
<defs>
<clipPath id="clip0_6013_33858">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>`;
} else {
prependIcon.innerHTML = `<g clip-path="url(#clip0_6083_34804)">
<path d="M11.4 15.2H12.6V11.2H11.4V15.2ZM12 10C12.1667 10 12.3056 9.94444 12.4167 9.83333C12.5389 9.71111 12.6 9.56667 12.6 9.4C12.6 9.23333 12.5389 9.09444 12.4167 8.98333C12.3056 8.86111 12.1667 8.8 12 8.8C11.8333 8.8 11.6889 8.86111 11.5667 8.98333C11.4556 9.09444 11.4 9.23333 11.4 9.4C11.4 9.56667 11.4556 9.71111 11.5667 9.83333C11.6889 9.94444 11.8333 10 12 10ZM12 18.4C11.1222 18.4 10.2944 18.2333 9.51667 17.9C8.73889 17.5667 8.05556 17.1111 7.46667 16.5333C6.88889 15.9444 6.43333 15.2611 6.1 14.4833C5.76667 13.7056 5.6 12.8778 5.6 12C5.6 11.1111 5.76667 10.2833 6.1 9.51667C6.43333 8.73889 6.88889 8.06111 7.46667 7.48333C8.05556 6.89444 8.73889 6.43333 9.51667 6.1C10.2944 5.76667 11.1222 5.6 12 5.6C12.8889 5.6 13.7167 5.76667 14.4833 6.1C15.2611 6.43333 15.9389 6.89444 16.5167 7.48333C17.1056 8.06111 17.5667 8.73889 17.9 9.51667C18.2333 10.2833 18.4 11.1111 18.4 12C18.4 12.8778 18.2333 13.7056 17.9 14.4833C17.5667 15.2611 17.1056 15.9444 16.5167 16.5333C15.9389 17.1111 15.2611 17.5667 14.4833 17.9C13.7167 18.2333 12.8889 18.4 12 18.4ZM12 17.2C13.4444 17.2 14.6722 16.6944 15.6833 15.6833C16.6944 14.6722 17.2 13.4444 17.2 12C17.2 10.5556 16.6944 9.32778 15.6833 8.31667C14.6722 7.30555 13.4444 6.8 12 6.8C10.5556 6.8 9.32778 7.30555 8.31667 8.31667C7.30556 9.32778 6.8 10.5556 6.8 12C6.8 13.4444 7.30556 14.6722 8.31667 15.6833C9.32778 16.6944 10.5556 17.2 12 17.2Z" fill="#212121"/>
</g>
<defs>
<clipPath id="clip0_6083_34804">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>`;
firebaseText.innerText = "Preview backend running in this workspace.";
}
firebaseText.setAttribute("id", firebaseTextId);
}
if (document.readyState === "loading") {
window.addEventListener("DOMContentLoaded", setupDom);
} else {
setupDom();
}
}
function getUA() {
if (typeof navigator !== "undefined" && typeof navigator["userAgent"] === "string") {
return navigator["userAgent"];
} else {
return "";
}
}
function isMobileCordova() {
return typeof window !== "undefined" && // @ts-ignore Setting up an broadly applicable index signature for Window
// just to deal with this case would probably be a bad idea.
!!(window["cordova"] || window["phonegap"] || window["PhoneGap"]) && /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA());
}
function isCloudflareWorker() {
return typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers";
}
function isBrowserExtension() {
const runtime = typeof chrome === "object" ? chrome.runtime : typeof browser === "object" ? browser.runtime : void 0;
return typeof runtime === "object" && runtime.id !== void 0;
}
function isReactNative() {
return typeof navigator === "object" && navigator["product"] === "ReactNative";
}
function isIndexedDBAvailable() {
try {
return typeof indexedDB === "object";
} catch (e) {
return false;
}
}
function validateIndexedDBOpenable() {
return new Promise((resolve, reject) => {
try {
let preExist = true;
const DB_CHECK_NAME = "validate-browser-context-for-indexeddb-analytics-module";
const request = self.indexedDB.open(DB_CHECK_NAME);
request.onsuccess = () => {
request.result.close();
if (!preExist) {
self.indexedDB.deleteDatabase(DB_CHECK_NAME);
}
resolve(true);
};
request.onupgradeneeded = () => {
preExist = false;
};
request.onerror = () => {
reject(request.error?.message || "");
};
} catch (error) {
reject(error);
}
});
}
function replaceTemplate(template, data) {
return template.replace(PATTERN, (_, key) => {
const value = data[key];
return value != null ? String(value) : `<${key}?>`;
});
}
function deepEqual(a, b) {
if (a === b) {
return true;
}
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
for (const k of aKeys) {
if (!bKeys.includes(k)) {
return false;
}
const aProp = a[k];
const bProp = b[k];
if (isObject(aProp) && isObject(bProp)) {
if (!deepEqual(aProp, bProp)) {
return false;
}
} else if (aProp !== bProp) {
return false;
}
}
for (const k of bKeys) {
if (!aKeys.includes(k)) {
return false;
}
}
return true;
}
function isObject(thing) {
return thing !== null && typeof thing === "object";
}
function querystring(querystringParams) {
const params = [];
for (const [key, value] of Object.entries(querystringParams)) {
if (Array.isArray(value)) {
value.forEach((arrayVal) => {
params.push(encodeURIComponent(key) + "=" + encodeURIComponent(arrayVal));
});
} else {
params.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
}
return params.length ? "&" + params.join("&") : "";
}
function querystringDecode(querystring2) {
const obj = {};
const tokens = querystring2.replace(/^\?/, "").split("&");
tokens.forEach((token) => {
if (token) {
const [key, value] = token.split("=");
obj[decodeURIComponent(key)] = decodeURIComponent(value);
}
});
return obj;
}
function extractQuerystring(url) {
const queryStart = url.indexOf("?");
if (!queryStart) {
return "";
}
const fragmentStart = url.indexOf("#", queryStart);
return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : void 0);
}
function createSubscribe(executor, onNoObservers) {
const proxy = new ObserverProxy(executor, onNoObservers);
return proxy.subscribe.bind(proxy);
}
function implementsAnyMethods(obj, methods) {
if (typeof obj !== "object" || obj === null) {
return false;
}
for (const method of methods) {
if (method in obj && typeof obj[method] === "function") {
return true;
}
}
return false;
}
function noop() {
}
function getModularInstance(service) {
if (service && service._delegate) {
return service._delegate;
} else {
return service;
}
}
var CONSTANTS, stringToByteArray$1, byteArrayToString, base64, DecodeBase64StringError, base64Encode, base64urlEncodeWithoutPadding, base64Decode, getDefaultsFromGlobal, getDefaultsFromEnvVariable, getDefaultsFromCookie, getDefaults, getDefaultEmulatorHost, getDefaultEmulatorHostnameAndPort, getDefaultAppConfig, Deferred, emulatorStatus, previouslyDismissed, ERROR_NAME, FirebaseError, ErrorFactory, PATTERN, ObserverProxy, MAX_VALUE_MILLIS;
var init_index_node_esm = __esm({
"node_modules/@firebase/util/dist/node-esm/index.node.esm.js"() {
init_postinstall();
CONSTANTS = {
/**
* @define {boolean} Whether this is the client Node.js SDK.
*/
NODE_CLIENT: false,
/**
* @define {boolean} Whether this is the Admin Node.js SDK.
*/
NODE_ADMIN: false,
/**
* Firebase SDK Version
*/
SDK_VERSION: "${JSCORE_VERSION}"
};
stringToByteArray$1 = function(str) {
const out = [];
let p = 0;
for (let i = 0; i < str.length; i++) {
let c = str.charCodeAt(i);
if (c < 128) {
out[p++] = c;
} else if (c < 2048) {
out[p++] = c >> 6 | 192;
out[p++] = c & 63 | 128;
} else if ((c & 64512) === 55296 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) === 56320) {
c = 65536 + ((c & 1023) << 10) + (str.charCodeAt(++i) & 1023);
out[p++] = c >> 18 | 240;
out[p++] = c >> 12 & 63 | 128;
out[p++] = c >> 6 & 63 | 128;
out[p++] = c & 63 | 128;
} else {
out[p++] = c >> 12 | 224;
out[p++] = c >> 6 & 63 | 128;
out[p++] = c & 63 | 128;
}
}
return out;
};
byteArrayToString = function(bytes) {
const out = [];
let pos = 0, c = 0;
while (pos < bytes.length) {
const c1 = bytes[pos++];
if (c1 < 128) {
out[c++] = String.fromCharCode(c1);
} else if (c1 > 191 && c1 < 224) {
const c2 = bytes[pos++];
out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
} else if (c1 > 239 && c1 < 365) {
const c2 = bytes[pos++];
const c3 = bytes[pos++];
const c4 = bytes[pos++];
const u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 65536;
out[c++] = String.fromCharCode(55296 + (u >> 10));
out[c++] = String.fromCharCode(56320 + (u & 1023));
} else {
const c2 = bytes[pos++];
const c3 = bytes[pos++];
out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
}
}
return out.join("");
};
base64 = {
/**
* Maps bytes to characters.
*/
byteToCharMap_: null,
/**
* Maps characters to bytes.
*/
charToByteMap_: null,
/**
* Maps bytes to websafe characters.
* @private
*/
byteToCharMapWebSafe_: null,
/**
* Maps websafe characters to bytes.
* @private
*/
charToByteMapWebSafe_: null,
/**
* Our default alphabet, shared between
* ENCODED_VALS and ENCODED_VALS_WEBSAFE
*/
ENCODED_VALS_BASE: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
/**
* Our default alphabet. Value 64 (=) is special; it means "nothing."
*/
get ENCODED_VALS() {
return this.ENCODED_VALS_BASE + "+/=";
},
/**
* Our websafe alphabet.
*/
get ENCODED_VALS_WEBSAFE() {
return this.ENCODED_VALS_BASE + "-_.";
},
/**
* Whether this browser supports the atob and btoa functions. This extension
* started at Mozilla but is now implemented by many browsers. We use the
* ASSUME_* variables to avoid pulling in the full useragent detection library
* but still allowing the standard per-browser compilations.
*
*/
HAS_NATIVE_SUPPORT: typeof atob === "function",
/**
* Base64-encode an array of bytes.
*
* @param input An array of bytes (numbers with
* value in [0, 255]) to encode.
* @param webSafe Boolean indicating we should use the
* alternative alphabet.
* @return The base64 encoded string.
*/
encodeByteArray(input, webSafe) {
if (!Array.isArray(input)) {
throw Error("encodeByteArray takes an array as a parameter");
}
this.init_();
const byteToCharMap = webSafe ? this.byteToCharMapWebSafe_ : this.byteToCharMap_;
const output = [];
for (let i = 0; i < input.length; i += 3) {
const byte1 = input[i];
const haveByte2 = i + 1 < input.length;
const byte2 = haveByte2 ? input[i + 1] : 0;
const haveByte3 = i + 2 < input.length;
const byte3 = haveByte3 ? input[i + 2] : 0;
const outByte1 = byte1 >> 2;
const outByte2 = (byte1 & 3) << 4 | byte2 >> 4;
let outByte3 = (byte2 & 15) << 2 | byte3 >> 6;
let outByte4 = byte3 & 63;
if (!haveByte3) {
outByte4 = 64;
if (!haveByte2) {
outByte3 = 64;
}
}
output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
}
return output.join("");
},
/**
* Base64-encode a string.
*
* @param input A string to encode.
* @param webSafe If true, we should use the
* alternative alphabet.
* @return The base64 encoded string.
*/
encodeString(input, webSafe) {
if (this.HAS_NATIVE_SUPPORT && !webSafe) {
return btoa(input);
}
return this.encodeByteArray(stringToByteArray$1(input), webSafe);
},
/**
* Base64-decode a string.
*
* @param input to decode.
* @param webSafe True if we should use the
* alternative alphabet.
* @return string representing the decoded value.
*/
decodeString(input, webSafe) {
if (this.HAS_NATIVE_SUPPORT && !webSafe) {
return atob(input);
}
return byteArrayToString(this.decodeStringToByteArray(input, webSafe));
},
/**
* Base64-decode a string.
*
* In base-64 decoding, groups of four characters are converted into three
* bytes. If the encoder did not apply padding, the input length may not
* be a multiple of 4.
*
* In this case, the last group will have fewer than 4 characters, and
* padding will be inferred. If the group has one or two characters, it decodes
* to one byte. If the group has three characters, it decodes to two bytes.
*
* @param input Input to decode.
* @param webSafe True if we should use the web-safe alphabet.
* @return bytes representing the decoded value.
*/
decodeStringToByteArray(input, webSafe) {
this.init_();
const charToByteMap = webSafe ? this.charToByteMapWebSafe_ : this.charToByteMap_;
const output = [];
for (let i = 0; i < input.length; ) {
const byte1 = charToByteMap[input.charAt(i++)];
const haveByte2 = i < input.length;
const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
++i;
const haveByte3 = i < input.length;
const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
++i;
const haveByte4 = i < input.length;
const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
++i;
if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
throw new DecodeBase64StringError();
}
const outByte1 = byte1 << 2 | byte2 >> 4;
output.push(outByte1);
if (byte3 !== 64) {
const outByte2 = byte2 << 4 & 240 | byte3 >> 2;
output.push(outByte2);
if (byte4 !== 64) {
const outByte3 = byte3 << 6 & 192 | byte4;
output.push(outByte3);
}
}
}
return output;
},
/**
* Lazy static initialization function. Called before
* accessing any of the static map variables.
* @private
*/
init_() {
if (!this.byteToCharMap_) {
this.byteToCharMap_ = {};
this.charToByteMap_ = {};
this.byteToCharMapWebSafe_ = {};
this.charToByteMapWebSafe_ = {};
for (let i = 0; i < this.ENCODED_VALS.length; i++) {
this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
this.charToByteMap_[this.byteToCharMap_[i]] = i;
this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;
if (i >= this.ENCODED_VALS_BASE.length) {
this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
}
}
}
}
};
DecodeBase64StringError = class extends Error {
constructor() {
super(...arguments);
this.name = "DecodeBase64StringError";
}
};
base64Encode = function(str) {
const utf8Bytes = stringToByteArray$1(str);
return base64.encodeByteArray(utf8Bytes, true);
};
base64urlEncodeWithoutPadding = function(str) {
return base64Encode(str).replace(/\./g, "");
};
base64Decode = function(str) {
try {
return base64.decodeString(str, true);
} catch (e) {
console.error("base64Decode failed: ", e);
}
return null;
};
getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;
getDefaultsFromEnvVariable = () => {
if (typeof process === "undefined" || typeof process.env === "undefined") {
return;
}
const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;
if (defaultsJsonString) {
return JSON.parse(defaultsJsonString);
}
};
getDefaultsFromCookie = () => {
if (typeof document === "undefined") {
return;
}
let match;
try {
match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
} catch (e) {
return;
}
const decoded = match && base64Decode(match[1]);
return decoded && JSON.parse(decoded);
};
getDefaults = () => {
try {
return getDefaultsFromPostinstall() || getDefaultsFromGlobal() || getDefaultsFromEnvVariable() || getDefaultsFromCookie();
} catch (e) {
console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
return;
}
};
getDefaultEmulatorHost = (productName) => getDefaults()?.emulatorHosts?.[productName];
getDefaultEmulatorHostnameAndPort = (productName) => {
const host = getDefaultEmulatorHost(productName);
if (!host) {
return void 0;
}
const separatorIndex = host.lastIndexOf(":");
if (separatorIndex <= 0 || separatorIndex + 1 === host.length) {
throw new Error(`Invalid host ${host} with no separate hostname and port!`);
}
const port = parseInt(host.substring(separatorIndex + 1), 10);
if (host[0] === "[") {
return [host.substring(1, separatorIndex - 1), port];
} else {
return [host.substring(0, separatorIndex), port];
}
};
getDefaultAppConfig = () => getDefaults()?.config;
Deferred = class {
constructor() {
this.reject = () => {
};
this.resolve = () => {
};
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
/**
* Our API internals are not promisified and cannot because our callback APIs have subtle expectations around
* invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
* and returns a node-style callback which will resolve or reject the Deferred's promise.
*/
wrapCallback(callback) {
return (error, value) => {
if (error) {
this.reject(error);
} else {
this.resolve(value);
}
if (typeof callback === "function") {
this.promise.catch(() => {
});
if (callback.length === 1) {
callback(error);
} else {
callback(error, value);
}
}
};
}
};
emulatorStatus = {};
previouslyDismissed = false;
ERROR_NAME = "FirebaseError";
FirebaseError = class _FirebaseError extends Error {
constructor(code, message, customData) {
super(message);
this.code = code;
this.customData = customData;
this.name = ERROR_NAME;
Object.setPrototypeOf(this, _FirebaseError.prototype);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ErrorFactory.prototype.create);
}
}
};
ErrorFactory = class {
constructor(service, serviceName, errors) {
this.service = service;
this.serviceName = serviceName;
this.errors = errors;
}
create(code, ...data) {
const customData = data[0] || {};
const fullCode = `${this.service}/${code}`;
const template = this.errors[code];
const message = template ? replaceTemplate(template, customData) : "Error";
const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
const error = new FirebaseError(fullCode, fullMessage, customData);
return error;
}
};
PATTERN = /\{\$([^}]+)}/g;
ObserverProxy = class {
/**
* @param executor Function which can make calls to a single Observer
* as a proxy.
* @param onNoObservers Callback when count of Observers goes to zero.
*/
constructor(executor, onNoObservers) {
this.observers = [];
this.unsubscribes = [];
this.observerCount = 0;
this.task = Promise.resolve();
this.finalized = false;
this.onNoObservers = onNoObservers;
this.task.then(() => {
executor(this);
}).catch((e) => {
this.error(e);
});
}
next(value) {
this.forEachObserver((observer) => {
observer.next(value);
});
}
error(error) {
this.forEachObserver((observer) => {
observer.error(error);
});
this.close(error);
}
complete() {
this.forEachObserver((observer) => {
observer.complete();
});
this.close();
}
/**
* Subscribe function that can be used to add an Observer to the fan-out list.
*
* - We require that no event is sent to a subscriber synchronously to their
* call to subscribe().
*/
subscribe(nextOrObserver, error, complete) {
let observer;
if (nextOrObserver === void 0 && error === void 0 && complete === void 0) {
throw new Error("Missing Observer.");
}
if (implementsAnyMethods(nextOrObserver, [
"next",
"error",
"complete"
])) {
observer = nextOrObserver;
} else {
observer = {
next: nextOrObserver,
error,
complete
};
}
if (observer.next === void 0) {
observer.next = noop;
}
if (observer.error === void 0) {
observer.error = noop;
}
if (observer.complete === void 0) {
observer.complete = noop;
}
const unsub = this.unsubscribeOne.bind(this, this.observers.length);
if (this.finalized) {
this.task.then(() => {
try {
if (this.finalError) {
observer.error(this.finalError);
} else {
observer.complete();
}
} catch (e) {
}
return;
});
}
this.observers.push(observer);
return unsub;
}
// Unsubscribe is synchronous - we guarantee that no events are sent to
// any unsubscribed Observer.
unsubscribeOne(i) {
if (this.observers === void 0 || this.observers[i] === void 0) {
return;
}
delete this.observers[i];
this.observerCount -= 1;
if (this.observerCount === 0 && this.onNoObservers !== void 0) {
this.onNoObservers(this);
}
}
forEachObserver(fn) {
if (this.finalized) {
return;
}
for (let i = 0; i < this.observers.length; i++) {
this.sendOne(i, fn);
}
}
// Call the Observer via one of it's callback function. We are careful to
// confirm that the observe has not been unsubscribed since this asynchronous
// function had been queued.
sendOne(i, fn) {
this.task.then(() => {
if (this.observers !== void 0 && this.observers[i] !== void 0) {
try {
fn(this.observers[i]);
} catch (e) {
if (typeof console !== "undefined" && console.error) {
console.error(e);
}
}
}
});
}
close(err) {
if (this.finalized) {
return;
}
this.finalized = true;
if (err !== void 0) {
this.finalError = err;
}
this.task.then(() => {
this.observers = void 0;
this.onNoObservers = void 0;
});
}
};
MAX_VALUE_MILLIS = 4 * 60 * 60 * 1e3;
CONSTANTS.NODE_CLIENT = true;
}
});
// node_modules/@firebase/component/dist/esm/index.esm.js
function normalizeIdentifierForFactory(identifier) {
return identifier === DEFAULT_ENTRY_NAME ? void 0 : identifier;
}
function isComponentEager(component) {
return component.instantiationMode === "EAGER";
}
var Component, DEFAULT_ENTRY_NAME, Provider, ComponentContainer;
var init_index_esm = __esm({
"node_modules/@firebase/component/dist/esm/index.esm.js"() {
init_index_node_esm();
Component = class {
/**
*
* @param name The public service name, e.g. app, auth, firestore, database
* @param instanceFactory Service factory responsible for creating the public interface
* @param type whether the service provided by the component is public or private
*/
constructor(name6, instanceFactory, type) {
this.name = name6;
this.instanceFactory = instanceFactory;
this.type = type;
this.multipleInstances = false;
this.serviceProps = {};
this.instantiationMode = "LAZY";
this.onInstanceCreated = null;
}
setInstantiationMode(mode) {
this.instantiationMode = mode;
return this;
}
setMultipleInstances(multipleInstances) {
this.multipleInstances = multipleInstances;
return this;
}
setServiceProps(props) {
this.serviceProps = props;
return this;
}
setInstanceCreatedCallback(callback) {
this.onInstanceCreated = callback;
return this;
}
};
DEFAULT_ENTRY_NAME = "[DEFAULT]";
Provider = class {
constructor(name6, container) {
this.name = name6;
this.container = container;
this.component = null;
this.instances = /* @__PURE__ */ new Map();
this.instancesDeferred = /* @__PURE__ */ new Map();
this.instancesOptions = /* @__PURE__ */ new Map();
this.onInitCallbacks = /* @__PURE__ */ new Map();
}
/**
* @param identifier A provider can provide multiple instances of a service
* if this.component.multipleInstances is true.
*/
get(identifier) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
if (!this.instancesDeferred.has(normalizedIdentifier)) {
const deferred = new Deferred();
this.instancesDeferred.set(normalizedIdentifier, deferred);
if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) {
try {
const instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
if (instance) {
deferred.resolve(instance);
}
} catch (e) {
}
}
}
return this.instancesDeferred.get(normalizedIdentifier).promise;
}
getImmediate(options) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(options?.identifier);
const optional = options?.optional ?? false;
if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) {
try {
return this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
} catch (e) {
if (optional) {
return null;
} else {
throw e;
}
}
} else {
if (optional) {
return null;
} else {
throw Error(`Service ${this.name} is not available`);
}
}
}
getComponent() {
return this.component;
}
setComponent(component) {
if (component.name !== this.name) {
throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
}
if (this.component) {
throw Error(`Component for ${this.name} has already been provided`);
}
this.component = component;
if (!this.shouldAutoInitialize()) {
return;
}
if (isComponentEager(component)) {
try {
this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME });
} catch (e) {
}
}
for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
try {
const instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
instanceDeferred.resolve(instance);
} catch (e) {
}
}
}
clearInstance(identifier = DEFAULT_ENTRY_NAME) {
this.instancesDeferred.delete(identifier);
this.instancesOptions.delete(identifier);
this.instances.delete(identifier);
}
// app.delete() will call this method on every provider to delete the services
// TODO: should we mark the provider as deleted?
async delete() {
const services = Array.from(this.instances.values());
await Promise.all([
...services.filter((service) => "INTERNAL" in service).map((service) => service.INTERNAL.delete()),
...services.filter((service) => "_delete" in service).map((service) => service._delete())
]);
}
isComponentSet() {
return this.component != null;
}
isInitialized(identifier = DEFAULT_ENTRY_NAME) {
return this.instances.has(identifier);
}
getOptions(identifier = DEFAULT_ENTRY_NAME) {
return this.instancesOptions.get(identifier) || {};
}
initialize(opts = {}) {
const { options = {} } = opts;
const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
if (this.isInitialized(normalizedIdentifier)) {
throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
}
if (!this.isComponentSet()) {
throw Error(`Component ${this.name} has not been registered yet`);
}
const instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier,
options
});
for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
if (normalizedIdentifier === normalizedDeferredIdentifier) {
instanceDeferred.resolve(instance);
}
}
return instance;
}
/**
*
* @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().
* The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
*
* @param identifier An optional instance identifier
* @returns a function to unregister the callback
*/
onInit(callback, identifier) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
const existingCallbacks = this.onInitCallbacks.get(normalizedIdentifier) ?? /* @__PURE__ */ new Set();
existingCallbacks.add(callback);
this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
const existingInstance = this.instances.get(normalizedIdentifier);
if (existingInstance) {
callback(existingInstance, normalizedIdentifier);
}
return () => {
existingCallbacks.delete(callback);
};
}
/**
* Invoke onInit callbacks synchronously
* @param instance the service instance`
*/
invokeOnInitCallbacks(instance, identifier) {
const callbacks = this.onInitCallbacks.get(identifier);
if (!callbacks) {
return;
}
for (const callback of callbacks) {
try {
callback(instance, identifier);
} catch {
}
}
}
getOrInitializeService({ instanceIdentifier, options = {} }) {
let instance = this.instances.get(instanceIdentifier);
if (!instance && this.component) {
instance = this.component.instanceFactory(this.container, {
instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
options
});
this.instances.set(instanceIdentifier, instance);
this.instancesOptions.set(instanceIdentifier, options);
this.invokeOnInitCallbacks(instance, instanceIdentifier);
if (this.component.onInstanceCreated) {
try {
this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
} catch {
}
}
}
return instance || null;
}
normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME) {
if (this.component) {
return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME;
} else {
return identifier;
}
}
shouldAutoInitialize() {
return !!this.component && this.component.instantiationMode !== "EXPLICIT";
}
};
ComponentContainer = class {
constructor(name6) {
this.name = name6;
this.providers = /* @__PURE__ */ new Map();
}
/**
*
* @param component Component being added
* @param overwrite When a component with the same name has already been registered,
* if overwrite is true: overwrite the existing component with the new component and create a new
* provider with the new component. It can be useful in tests where you want to use different mocks
* for different tests.
* if overwrite is false: throw an exception
*/
addComponent(component) {
const provider = this.getProvider(component.name);
if (provider.isComponentSet()) {
throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
}
provider.setComponent(component);
}
addOrOverwriteComponent(component) {
const provider = this.getProvider(component.name);
if (provider.isComponentSet()) {
this.providers.delete(component.name);
}
this.addComponent(component);
}
/**
* getProvider provides a type safe interface where it can only be called with a field name
* present in NameServiceMapping interface.
*
* Firebase SDKs providing services should extend NameServiceMapping interface to register
* themselves.
*/
getProvider(name6) {
if (this.providers.has(name6)) {
return this.providers.get(name6);
}
const provider = new Provider(name6, this);
this.providers.set(name6, provider);
return provider;
}
getProviders() {
return Array.from(this.providers.values());
}
};
}
});
// node_modules/@firebase/logger/dist/esm/index.esm.js
var instances, LogLevel, levelStringToEnum, defaultLogLevel, ConsoleMethod, defaultLogHandler, Logger;
var init_index_esm2 = __esm({
"node_modules/@firebase/logger/dist/esm/index.esm.js"() {
instances = [];
(function(LogLevel2) {
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
LogLevel2[LogLevel2["VERBOSE"] = 1] = "VERBOSE";
LogLevel2[LogLevel2["INFO"] = 2] = "INFO";
LogLevel2[LogLevel2["WARN"] = 3] = "WARN";
LogLevel2[LogLevel2["ERROR"] = 4] = "ERROR";
LogLevel2[LogLevel2["SILENT"] = 5] = "SILENT";
})(LogLevel || (LogLevel = {}));
levelStringToEnum = {
"debug": LogLevel.DEBUG,
"verbose": LogLevel.VERBOSE,
"info": LogLevel.INFO,
"warn": LogLevel.WARN,
"error": LogLevel.ERROR,
"silent": LogLevel.SILENT
};
defaultLogLevel = LogLevel.INFO;
ConsoleMethod = {
[LogLevel.DEBUG]: "log",
[LogLevel.VERBOSE]: "log",
[LogLevel.INFO]: "info",
[LogLevel.WARN]: "warn",
[LogLevel.ERROR]: "error"
};
defaultLogHandler = (instance, logType, ...args) => {
if (logType < instance.logLevel) {
return;
}
const now = (/* @__PURE__ */ new Date()).toISOString();
const method = ConsoleMethod[logType];
if (method) {
console[method](`[${now}] ${instance.name}:`, ...args);
} else {
throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
}
};
Logger = class {
/**
* Gives you an instance of a Logger to capture messages according to
* Firebase's logging scheme.
*
* @param name The name that the logs will be associated with
*/
constructor(name6) {
this.name = name6;
this._logLevel = defaultLogLevel;
this._logHandler = defaultLogHandler;
this._userLogHandler = null;
instances.push(this);
}
get logLevel() {
return this._logLevel;
}
set logLevel(val) {
if (!(val in LogLevel)) {
throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
}
this._logLevel = val;
}
// Workaround for setter/getter having to be the same type.
setLogLevel(val) {
this._logLevel = typeof val === "string" ? levelStringToEnum[val] : val;
}
get logHandler() {
return this._logHandler;
}
set logHandler(val) {
if (typeof val !== "function") {
throw new TypeError("Value assigned to `logHandler` must be a function");
}
this._logHandler = val;
}
get userLogHandler() {
return this._userLogHandler;
}
set userLogHandler(val) {
this._userLogHandler = val;
}
/**
* The functions below are all based on the `console` interface
*/
debug(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);
this._logHandler(this, LogLevel.DEBUG, ...args);
}
log(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.VERBOSE, ...args);
this._logHandler(this, LogLevel.VERBOSE, ...args);
}
info(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);
this._logHandler(this, LogLevel.INFO, ...args);
}
warn(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);
this._logHandler(this, LogLevel.WARN, ...args);
}
error(...args) {
this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);
this._logHandler(this, LogLevel.ERROR, ...args);
}
};
}
});
// node_modules/idb/build/wrap-idb-value.js
function getIdbProxyableTypes() {
return idbProxyableTypes || (idbProxyableTypes = [
IDBDatabase,
IDBObjectStore,
IDBIndex,
IDBCursor,
IDBTransaction
]);
}
function getCursorAdvanceMethods() {
return cursorAdvanceMethods || (cursorAdvanceMethods = [
IDBCursor.prototype.advance,
IDBCursor.prototype.continue,
IDBCursor.prototype.continuePrimaryKey
]);
}
function promisifyRequest(request) {
const promise = new Promise((resolve, reject) => {
const unlisten = () => {
request.removeEventListener("success", success);
request.removeEventListener("error", error);
};
const success = () => {
resolve(wrap(request.result));
unlisten();
};
const error = () => {
reject(request.error);
unlisten();
};
request.addEventListener("success", success);
request.addEventListener("error", error);
});
promise.then((value) => {
if (value instanceof IDBCursor) {
cursorRequestMap.set(value, request);
}
}).catch(() => {
});
reverseTransformCache.set(promise, request);
return promise;
}
function cacheDonePromiseForTransaction(tx) {
if (transactionDoneMap.has(tx))
return;
const done = new Promise((resolve, reject) => {
const unlisten = () => {
tx.removeEventListener("complete", complete);
tx.removeEventListener("error", error);
tx.removeEventListener("abort", error);
};
const complete = () => {
resolve();
unlisten();
};
const error = () => {
reject(tx.error || new DOMException("AbortError", "AbortError"));
unlisten();
};
tx.addEventListener("complete", complete);
tx.addEventListener("error", error);
tx.addEventListener("abort", error);
});
transactionDoneMap.set(tx, done);
}
function replaceTraps(callback) {
idbProxyTraps = callback(idbProxyTraps);
}
function wrapFunction(func) {
if (func === IDBDatabase.prototype.transaction && !("objectStoreNames" in IDBTransaction.prototype)) {
return function(storeNames, ...args) {
const tx = func.call(unwrap(this), storeNames, ...args);
transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
return wrap(tx);
};
}
if (getCursorAdvanceMethods().includes(func)) {
return function(...args) {
func.apply(unwrap(this), args);
return wrap(cursorRequestMap.get(this));
};
}
return function(...args) {
return wrap(func.apply(unwrap(this), args));
};
}
function transformCachableValue(value) {
if (typeof value === "function")
return wrapFunction(value);
if (value instanceof IDBTransaction)
cacheDonePromiseForTransaction(value);
if (instanceOfAny(value, getIdbProxyableTypes()))
return new Proxy(value, idbProxyTraps);
return value;
}
function wrap(value) {
if (value instanceof IDBRequest)
return promisifyRequest(value);
if (transformCache.has(value))
return transformCache.get(value);
const newValue = transformCachableValue(value);
if (newValue !== value) {
transformCache.set(value, newValue);
reverseTransformCache.set(newValue, value);
}
return newValue;
}
var instanceOfAny, idbProxyableTypes, cursorAdvanceMethods, cursorRequestMap, transactionDoneMap, transactionStoreNamesMap, transformCache, reverseTransformCache, idbProxyTraps, unwrap;
var init_wrap_idb_value = __esm({
"node_modules/idb/build/wrap-idb-value.js"() {
instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
cursorRequestMap = /* @__PURE__ */ new WeakMap();
transactionDoneMap = /* @__PURE__ */ new WeakMap();
transactionStoreNamesMap = /* @__PURE__ */ new WeakMap();
transformCache = /* @__PURE__ */ new WeakMap();
reverseTransformCache = /* @__PURE__ */ new WeakMap();
idbProxyTraps = {
get(target, prop, receiver) {
if (target instanceof IDBTransaction) {
if (prop === "done")
return transactionDoneMap.get(target);
if (prop === "objectStoreNames") {
return target.objectStoreNames || transactionStoreNamesMap.get(target);
}
if (prop === "store") {
return receiver.objectStoreNames[1] ? void 0 : receiver.objectStore(receiver.objectStoreNames[0]);
}
}
return wrap(target[prop]);
},
set(target, prop, value) {
target[prop] = value;
return true;
},
has(target, prop) {
if (target instanceof IDBTransaction && (prop === "done" || prop === "store")) {
return true;
}
return prop in target;
}
};
unwrap = (value) => reverseTransformCache.get(value);
}
});
// node_modules/idb/build/index.js
var build_exports = {};
__export(build_exports, {
deleteDB: () => deleteDB,
openDB: () => openDB,
unwrap: () => unwrap,
wrap: () => wrap
});
function openDB(name6, version6, { blocked, upgrade, blocking, terminated } = {}) {
const request = indexedDB.open(name6, version6);
const openPromise = wrap(request);
if (upgrade) {
request.addEventListener("upgradeneeded", (event) => {
upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
});
}
if (blocked) {
request.addEventListener("blocked", (event) => blocked(
// Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
event.oldVersion,
event.newVersion,
event
));
}
openPromise.then((db) => {
if (terminated)
db.addEventListener("close", () => terminated());
if (blocking) {
db.addEventListener("versionchange", (event) => blocking(event.oldVersion, event.newVersion, event));
}
}).catch(() => {
});
return openPromise;
}
function deleteDB(name6, { blocked } = {}) {
const request = indexedDB.deleteDatabase(name6);
if (blocked) {
request.addEventListener("blocked", (event) => blocked(
// Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
event.oldVersion,
event
));
}
return wrap(request).then(() => void 0);
}
function getMethod(target, prop) {
if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === "string")) {
return;
}
if (cachedMethods.get(prop))
return cachedMethods.get(prop);
const targetFuncName = prop.replace(/FromIndex$/, "");
const useIndex = prop !== targetFuncName;
const isWrite = writeMethods.includes(targetFuncName);
if (
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
!(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName))
) {
return;
}
const method = async function(storeName, ...args) {
const tx = this.transaction(storeName, isWrite ? "readwrite" : "readonly");
let target2 = tx.store;
if (useIndex)
target2 = target2.index(args.shift());
return (await Promise.all([
target2[targetFuncName](...args),
isWrite && tx.done
]))[0];
};
cachedMethods.set(prop, method);
return method;
}
var readMethods, writeMethods, cachedMethods;
var init_build = __esm({
"node_modules/idb/build/index.js"() {
init_wrap_idb_value();
init_wrap_idb_value();
readMethods = ["get", "getKey", "getAll", "getAllKeys", "count"];
writeMethods = ["put", "add", "delete", "clear"];
cachedMethods = /* @__PURE__ */ new Map();
replaceTraps((oldTraps) => ({
...oldTraps,
get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop)
}));
}
});
// node_modules/@firebase/app/dist/esm/index.esm.js
function isVersionServiceProvider(provider) {
const component = provider.getComponent();
return component?.type === "VERSION";
}
function _addComponent(app2, component) {
try {
app2.container.addComponent(component);
} catch (e) {
logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app2.name}`, e);
}
}
function _registerComponent(component) {
const componentName = component.name;
if (_components.has(componentName)) {
logger.debug(`There were multiple attempts to register component ${componentName}.`);
return false;
}
_components.set(componentName, component);
for (const app2 of _apps.values()) {
_addComponent(app2, component);
}
for (const serverApp of _serverApps.values()) {
_addComponent(serverApp, component);
}
return true;
}
function _getProvider(app2, name6) {
const heartbeatController = app2.container.getProvider("heartbeat").getImmediate({ optional: true });
if (heartbeatController) {
void heartbeatController.triggerHeartbeat();
}
return app2.container.getProvider(name6);
}
function _isFirebaseServerApp(obj) {
if (obj === null || obj === void 0) {
return false;
}
return obj.settings !== void 0;
}
function initializeApp(_options, rawConfig = {}) {
let options = _options;
if (typeof rawConfig !== "object") {
const name7 = rawConfig;
rawConfig = { name: name7 };
}
const config = {
name: DEFAULT_ENTRY_NAME2,
automaticDataCollectionEnabled: true,
...rawConfig
};
const name6 = config.name;
if (typeof name6 !== "string" || !name6) {
throw ERROR_FACTORY.create("bad-app-name", {
appName: String(name6)
});
}
options || (options = getDefaultAppConfig());
if (!options) {
throw ERROR_FACTORY.create(
"no-options"
/* AppError.NO_OPTIONS */
);
}
const existingApp = _apps.get(name6);
if (existingApp) {
if (deepEqual(options, existingApp.options) && deepEqual(config, existingApp.config)) {
return existingApp;
} else {
throw ERROR_FACTORY.create("duplicate-app", { appName: name6 });
}
}
const container = new ComponentContainer(name6);
for (const component of _components.values()) {
container.addComponent(component);
}
const newApp = new FirebaseAppImpl(options, config, container);
_apps.set(name6, newApp);
return newApp;
}
function getApp(name6 = DEFAULT_ENTRY_NAME2) {
const app2 = _apps.get(name6);
if (!app2 && name6 === DEFAULT_ENTRY_NAME2 && getDefaultAppConfig()) {
return initializeApp();
}
if (!app2) {
throw ERROR_FACTORY.create("no-app", { appName: name6 });
}
return app2;
}
function registerVersion(libraryKeyOrName, version6, variant) {
let library = PLATFORM_LOG_STRING[libraryKeyOrName] ?? libraryKeyOrName;
if (variant) {
library += `-${variant}`;
}
const libraryMismatch = library.match(/\s|\//);
const versionMismatch = version6.match(/\s|\//);
if (libraryMismatch || versionMismatch) {
const warning = [
`Unable to register library "${library}" with version "${version6}":`
];
if (libraryMismatch) {
warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
}
if (libraryMismatch && versionMismatch) {
warning.push("and");
}
if (versionMismatch) {
warning.push(`version name "${version6}" contains illegal characters (whitespace or "/")`);
}
logger.warn(warning.join(" "));
return;
}
_registerComponent(new Component(
`${library}-version`,
() => ({ library, version: version6 }),
"VERSION"
/* ComponentType.VERSION */
));
}
function getDbPromise() {
if (!dbPromise) {
dbPromise = openDB(DB_NAME, DB_VERSION, {
upgrade: (db, oldVersion) => {
switch (oldVersion) {
case 0:
try {
db.createObjectStore(STORE_NAME);
} catch (e) {
console.warn(e);
}
}
}
}).catch((e) => {
throw ERROR_FACTORY.create("idb-open", {
originalErrorMessage: e.message
});
});
}
return dbPromise;
}
async function readHeartbeatsFromIndexedDB(app2) {
try {
const db = await getDbPromise();
const tx = db.transaction(STORE_NAME);
const result = await tx.objectStore(STORE_NAME).get(computeKey(app2));
await tx.done;
return result;
} catch (e) {
if (e instanceof FirebaseError) {
logger.warn(e.message);
} else {
const idbGetError = ERROR_FACTORY.create("idb-get", {
originalErrorMessage: e?.message
});
logger.warn(idbGetError.message);
}
}
}
async function writeHeartbeatsToIndexedDB(app2, heartbeatObject) {
try {
const db = await getDbPromise();
const tx = db.transaction(STORE_NAME, "readwrite");
const objectStore = tx.objectStore(STORE_NAME);
await objectStore.put(heartbeatObject, computeKey(app2));
await tx.done;
} catch (e) {
if (e instanceof FirebaseError) {
logger.warn(e.message);
} else {
const idbGetError = ERROR_FACTORY.create("idb-set", {
originalErrorMessage: e?.message
});
logger.warn(idbGetError.message);
}
}
}
function computeKey(app2) {
return `${app2.name}!${app2.options.appId}`;
}
function getUTCDateString() {
const today = /* @__PURE__ */ new Date();
return today.toISOString().substring(0, 10);
}
function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
const heartbeatsToSend = [];
let unsentEntries = heartbeatsCache.slice();
for (const singleDateHeartbeat of heartbeatsCache) {
const heartbeatEntry = heartbeatsToSend.find((hb) => hb.agent === singleDateHeartbeat.agent);
if (!heartbeatEntry) {
heartbeatsToSend.push({
agent: singleDateHeartbeat.agent,
dates: [singleDateHeartbeat.date]
});
if (countBytes(heartbeatsToSend) > maxSize) {
heartbeatsToSend.pop();
break;
}
} else {
heartbeatEntry.dates.push(singleDateHeartbeat.date);
if (countBytes(heartbeatsToSend) > maxSize) {
heartbeatEntry.dates.pop();
break;
}
}
unsentEntries = unsentEntries.slice(1);
}
return {
heartbeatsToSend,
unsentEntries
};
}
function countBytes(heartbeatsCache) {
return base64urlEncodeWithoutPadding(
// heartbeatsCache wrapper properties
JSON.stringify({ version: 2, heartbeats: heartbeatsCache })
).length;
}
function getEarliestHeartbeatIdx(heartbeats) {
if (heartbeats.length === 0) {
return -1;
}
let earliestHeartbeatIdx = 0;
let earliestHeartbeatDate = heartbeats[0].date;
for (let i = 1; i < heartbeats.length; i++) {
if (heartbeats[i].date < earliestHeartbeatDate) {
earliestHeartbeatDate = heartbeats[i].date;
earliestHeartbeatIdx = i;
}
}
return earliestHeartbeatIdx;
}
function registerCoreComponents(variant) {
_registerComponent(new Component(
"platform-logger",
(container) => new PlatformLoggerServiceImpl(container),
"PRIVATE"
/* ComponentType.PRIVATE */
));
_registerComponent(new Component(
"heartbeat",
(container) => new HeartbeatServiceImpl(container),
"PRIVATE"
/* ComponentType.PRIVATE */
));
registerVersion(name$q, version$1, variant);
registerVersion(name$q, version$1, "esm2020");
registerVersion("fire-js", "");
}
var PlatformLoggerServiceImpl, name$q, version$1, logger, name$p, name$o, name$n, name$m, name$l, name$k, name$j, name$i, name$h, name$g, name$f, name$e, name$d, name$c, name$b, name$a, name$9, name$8, name$7, name$6, name$5, name$4, name$3, name$2, name$1, name, version, DEFAULT_ENTRY_NAME2, PLATFORM_LOG_STRING, _apps, _serverApps, _components, ERRORS, ERROR_FACTORY, FirebaseAppImpl, SDK_VERSION, DB_NAME, DB_VERSION, STORE_NAME, dbPromise, MAX_HEADER_BYTES, MAX_NUM_STORED_HEARTBEATS, HeartbeatServiceImpl, HeartbeatStorageImpl;
var init_index_esm3 = __esm({
"node_modules/@firebase/app/dist/esm/index.esm.js"() {
init_index_esm();
init_index_esm2();
init_index_node_esm();
init_index_node_esm();
init_build();
PlatformLoggerServiceImpl = class {
constructor(container) {
this.container = container;
}
// In initial implementation, this will be called by installations on
// auth token refresh, and installations will send this string.
getPlatformInfoString() {
const providers = this.container.getProviders();
return providers.map((provider) => {
if (isVersionServiceProvider(provider)) {
const service = provider.getImmediate();
return `${service.library}/${service.version}`;
} else {
return null;
}
}).filter((logString) => logString).join(" ");
}
};
name$q = "@firebase/app";
version$1 = "0.14.5";
logger = new Logger("@firebase/app");
name$p = "@firebase/app-compat";
name$o = "@firebase/analytics-compat";
name$n = "@firebase/analytics";
name$m = "@firebase/app-check-compat";
name$l = "@firebase/app-check";
name$k = "@firebase/auth";
name$j = "@firebase/auth-compat";
name$i = "@firebase/database";
name$h = "@firebase/data-connect";
name$g = "@firebase/database-compat";
name$f = "@firebase/functions";
name$e = "@firebase/functions-compat";
name$d = "@firebase/installations";
name$c = "@firebase/installations-compat";
name$b = "@firebase/messaging";
name$a = "@firebase/messaging-compat";
name$9 = "@firebase/performance";
name$8 = "@firebase/performance-compat";
name$7 = "@firebase/remote-config";
name$6 = "@firebase/remote-config-compat";
name$5 = "@firebase/storage";
name$4 = "@firebase/storage-compat";
name$3 = "@firebase/firestore";
name$2 = "@firebase/ai";
name$1 = "@firebase/firestore-compat";
name = "firebase";
version = "12.5.0";
DEFAULT_ENTRY_NAME2 = "[DEFAULT]";
PLATFORM_LOG_STRING = {
[name$q]: "fire-core",
[name$p]: "fire-core-compat",
[name$n]: "fire-analytics",
[name$o]: "fire-analytics-compat",
[name$l]: "fire-app-check",
[name$m]: "fire-app-check-compat",
[name$k]: "fire-auth",
[name$j]: "fire-auth-compat",
[name$i]: "fire-rtdb",
[name$h]: "fire-data-connect",
[name$g]: "fire-rtdb-compat",
[name$f]: "fire-fn",
[name$e]: "fire-fn-compat",
[name$d]: "fire-iid",
[name$c]: "fire-iid-compat",
[name$b]: "fire-fcm",
[name$a]: "fire-fcm-compat",
[name$9]: "fire-perf",
[name$8]: "fire-perf-compat",
[name$7]: "fire-rc",
[name$6]: "fire-rc-compat",
[name$5]: "fire-gcs",
[name$4]: "fire-gcs-compat",
[name$3]: "fire-fst",
[name$1]: "fire-fst-compat",
[name$2]: "fire-vertex",
"fire-js": "fire-js",
// Platform identifier for JS SDK.
[name]: "fire-js-all"
};
_apps = /* @__PURE__ */ new Map();
_serverApps = /* @__PURE__ */ new Map();
_components = /* @__PURE__ */ new Map();
ERRORS = {
[
"no-app"
/* AppError.NO_APP */
]: "No Firebase App '{$appName}' has been created - call initializeApp() first",
[
"bad-app-name"
/* AppError.BAD_APP_NAME */
]: "Illegal App name: '{$appName}'",
[
"duplicate-app"
/* AppError.DUPLICATE_APP */
]: "Firebase App named '{$appName}' already exists with different options or config",
[
"app-deleted"
/* AppError.APP_DELETED */
]: "Firebase App named '{$appName}' already deleted",
[
"server-app-deleted"
/* AppError.SERVER_APP_DELETED */
]: "Firebase Server App has been deleted",
[
"no-options"
/* AppError.NO_OPTIONS */
]: "Need to provide options, when not being deployed to hosting via source.",
[
"invalid-app-argument"
/* AppError.INVALID_APP_ARGUMENT */
]: "firebase.{$appName}() takes either no argument or a Firebase App instance.",
[
"invalid-log-argument"
/* AppError.INVALID_LOG_ARGUMENT */
]: "First argument to `onLog` must be null or a function.",
[
"idb-open"
/* AppError.IDB_OPEN */
]: "Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.",
[
"idb-get"
/* AppError.IDB_GET */
]: "Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.",
[
"idb-set"
/* AppError.IDB_WRITE */
]: "Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.",
[
"idb-delete"
/* AppError.IDB_DELETE */
]: "Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.",
[
"finalization-registry-not-supported"
/* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */
]: "FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.",
[
"invalid-server-app-environment"
/* AppError.INVALID_SERVER_APP_ENVIRONMENT */
]: "FirebaseServerApp is not for use in browser environments."
};
ERROR_FACTORY = new ErrorFactory("app", "Firebase", ERRORS);
FirebaseAppImpl = class {
constructor(options, config, container) {
this._isDeleted = false;
this._options = { ...options };
this._config = { ...config };
this._name = config.name;
this._automaticDataCollectionEnabled = config.automaticDataCollectionEnabled;
this._container = container;
this.container.addComponent(new Component(
"app",
() => this,
"PUBLIC"
/* ComponentType.PUBLIC */
));
}
get automaticDataCollectionEnabled() {
this.checkDestroyed();
return this._automaticDataCollectionEnabled;
}
set automaticDataCollectionEnabled(val) {
this.checkDestroyed();
this._automaticDataCollectionEnabled = val;
}
get name() {
this.checkDestroyed();
return this._name;
}
get options() {
this.checkDestroyed();
return this._options;
}
get config() {
this.checkDestroyed();
return this._config;
}
get container() {
return this._container;
}
get isDeleted() {
return this._isDeleted;
}
set isDeleted(val) {
this._isDeleted = val;
}
/**
* This function will throw an Error if the App has already been deleted -
* use before performing API actions on the App.
*/
checkDestroyed() {
if (this.isDeleted) {
throw ERROR_FACTORY.create("app-deleted", { appName: this._name });
}
}
};
SDK_VERSION = version;
DB_NAME = "firebase-heartbeat-database";
DB_VERSION = 1;
STORE_NAME = "firebase-heartbeat-store";
dbPromise = null;
MAX_HEADER_BYTES = 1024;
MAX_NUM_STORED_HEARTBEATS = 30;
HeartbeatServiceImpl = class {
constructor(container) {
this.container = container;
this._heartbeatsCache = null;
const app2 = this.container.getProvider("app").getImmediate();
this._storage = new HeartbeatStorageImpl(app2);
this._heartbeatsCachePromise = this._storage.read().then((result) => {
this._heartbeatsCache = result;
return result;
});
}
/**
* Called to report a heartbeat. The function will generate
* a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
* to IndexedDB.
* Note that we only store one heartbeat per day. So if a heartbeat for today is
* already logged, subsequent calls to this function in the same day will be ignored.
*/
async triggerHeartbeat() {
try {
const platformLogger = this.container.getProvider("platform-logger").getImmediate();
const agent = platformLogger.getPlatformInfoString();
const date = getUTCDateString();
if (this._heartbeatsCache?.heartbeats == null) {
this._heartbeatsCache = await this._heartbeatsCachePromise;
if (this._heartbeatsCache?.heartbeats == null) {
return;
}
}
if (this._heartbeatsCache.lastSentHeartbeatDate === date || this._heartbeatsCache.heartbeats.some((singleDateHeartbeat) => singleDateHeartbeat.date === date)) {
return;
} else {
this._heartbeatsCache.heartbeats.push({ date, agent });
if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS) {
const earliestHeartbeatIdx = getEarliestHeartbeatIdx(this._heartbeatsCache.heartbeats);
this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1);
}
}
return this._storage.overwrite(this._heartbeatsCache);
} catch (e) {
logger.warn(e);
}
}
/**
* Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
* It also clears all heartbeats from memory as well as in IndexedDB.
*
* NOTE: Consuming product SDKs should not send the header if this method
* returns an empty string.
*/
async getHeartbeatsHeader() {
try {
if (this._heartbeatsCache === null) {
await this._heartbeatsCachePromise;
}
if (this._heartbeatsCache?.heartbeats == null || this._heartbeatsCache.heartbeats.length === 0) {
return "";
}
const date = getUTCDateString();
const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
this._heartbeatsCache.lastSentHeartbeatDate = date;
if (unsentEntries.length > 0) {
this._heartbeatsCache.heartbeats = unsentEntries;
await this._storage.overwrite(this._heartbeatsCache);
} else {
this._heartbeatsCache.heartbeats = [];
void this._storage.overwrite(this._heartbeatsCache);
}
return headerString;
} catch (e) {
logger.warn(e);
return "";
}
}
};
HeartbeatStorageImpl = class {
constructor(app2) {
this.app = app2;
this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
}
async runIndexedDBEnvironmentCheck() {
if (!isIndexedDBAvailable()) {
return false;
} else {
return validateIndexedDBOpenable().then(() => true).catch(() => false);
}
}
/**
* Read all heartbeats.
*/
async read() {
const canUseIndexedDB = await this._canUseIndexedDBPromise;
if (!canUseIndexedDB) {
return { heartbeats: [] };
} else {
const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
if (idbHeartbeatObject?.heartbeats) {
return idbHeartbeatObject;
} else {
return { heartbeats: [] };
}
}
}
// overwrite the storage with the provided heartbeats
async overwrite(heartbeatsObject) {
const canUseIndexedDB = await this._canUseIndexedDBPromise;
if (!canUseIndexedDB) {
return;
} else {
const existingHeartbeatsObject = await this.read();
return writeHeartbeatsToIndexedDB(this.app, {
lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ?? existingHeartbeatsObject.lastSentHeartbeatDate,
heartbeats: heartbeatsObject.heartbeats
});
}
}
// add heartbeats
async add(heartbeatsObject) {
const canUseIndexedDB = await this._canUseIndexedDBPromise;
if (!canUseIndexedDB) {
return;
} else {
const existingHeartbeatsObject = await this.read();
return writeHeartbeatsToIndexedDB(this.app, {
lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ?? existingHeartbeatsObject.lastSentHeartbeatDate,
heartbeats: [
...existingHeartbeatsObject.heartbeats,
...heartbeatsObject.heartbeats
]
});
}
}
};
registerCoreComponents("");
}
});
// node_modules/firebase/app/dist/index.mjs
var name2, version2;
var init_dist = __esm({
"node_modules/firebase/app/dist/index.mjs"() {
init_index_esm3();
init_index_esm3();
name2 = "firebase";
version2 = "12.5.0";
registerVersion(name2, version2, "app");
}
});
// node_modules/@firebase/auth/dist/node-esm/totp-c8d207b9.js
function _debugErrorMap() {
return {
[
"admin-restricted-operation"
/* AuthErrorCode.ADMIN_ONLY_OPERATION */
]: "This operation is restricted to administrators only.",
[
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
]: "",
[
"app-not-authorized"
/* AuthErrorCode.APP_NOT_AUTHORIZED */
]: "This app, identified by the domain where it's hosted, is not authorized to use Firebase Authentication with the provided API key. Review your key configuration in the Google API console.",
[
"app-not-installed"
/* AuthErrorCode.APP_NOT_INSTALLED */
]: "The requested mobile application corresponding to the identifier (Android package name or iOS bundle ID) provided is not installed on this device.",
[
"captcha-check-failed"
/* AuthErrorCode.CAPTCHA_CHECK_FAILED */
]: "The reCAPTCHA response token provided is either invalid, expired, already used or the domain associated with it does not match the list of whitelisted domains.",
[
"code-expired"
/* AuthErrorCode.CODE_EXPIRED */
]: "The SMS code has expired. Please re-send the verification code to try again.",
[
"cordova-not-ready"
/* AuthErrorCode.CORDOVA_NOT_READY */
]: "Cordova framework is not ready.",
[
"cors-unsupported"
/* AuthErrorCode.CORS_UNSUPPORTED */
]: "This browser is not supported.",
[
"credential-already-in-use"
/* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */
]: "This credential is already associated with a different user account.",
[
"custom-token-mismatch"
/* AuthErrorCode.CREDENTIAL_MISMATCH */
]: "The custom token corresponds to a different audience.",
[
"requires-recent-login"
/* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
]: "This operation is sensitive and requires recent authentication. Log in again before retrying this request.",
[
"dependent-sdk-initialized-before-auth"
/* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
]: "Another Firebase SDK was initialized and is trying to use Auth before Auth is initialized. Please be sure to call `initializeAuth` or `getAuth` before starting any other Firebase SDK.",
[
"dynamic-link-not-activated"
/* AuthErrorCode.DYNAMIC_LINK_NOT_ACTIVATED */
]: "Please activate Dynamic Links in the Firebase Console and agree to the terms and conditions.",
[
"email-change-needs-verification"
/* AuthErrorCode.EMAIL_CHANGE_NEEDS_VERIFICATION */
]: "Multi-factor users must always have a verified email.",
[
"email-already-in-use"
/* AuthErrorCode.EMAIL_EXISTS */
]: "The email address is already in use by another account.",
[
"emulator-config-failed"
/* AuthErrorCode.EMULATOR_CONFIG_FAILED */
]: 'Auth instance has already been used to make a network call. Auth can no longer be configured to use the emulator. Try calling "connectAuthEmulator()" sooner.',
[
"expired-action-code"
/* AuthErrorCode.EXPIRED_OOB_CODE */
]: "The action code has expired.",
[
"cancelled-popup-request"
/* AuthErrorCode.EXPIRED_POPUP_REQUEST */
]: "This operation has been cancelled due to another conflicting popup being opened.",
[
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
]: "An internal AuthError has occurred.",
[
"invalid-app-credential"
/* AuthErrorCode.INVALID_APP_CREDENTIAL */
]: "The phone verification request contains an invalid application verifier. The reCAPTCHA token response is either invalid or expired.",
[
"invalid-app-id"
/* AuthErrorCode.INVALID_APP_ID */
]: "The mobile app identifier is not registered for the current project.",
[
"invalid-user-token"
/* AuthErrorCode.INVALID_AUTH */
]: "This user's credential isn't valid for this project. This can happen if the user's token has been tampered with, or if the user isn't for the project associated with this API key.",
[
"invalid-auth-event"
/* AuthErrorCode.INVALID_AUTH_EVENT */
]: "An internal AuthError has occurred.",
[
"invalid-verification-code"
/* AuthErrorCode.INVALID_CODE */
]: "The SMS verification code used to create the phone auth credential is invalid. Please resend the verification code sms and be sure to use the verification code provided by the user.",
[
"invalid-continue-uri"
/* AuthErrorCode.INVALID_CONTINUE_URI */
]: "The continue URL provided in the request is invalid.",
[
"invalid-cordova-configuration"
/* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
]: "The following Cordova plugins must be installed to enable OAuth sign-in: cordova-plugin-buildinfo, cordova-universal-links-plugin, cordova-plugin-browsertab, cordova-plugin-inappbrowser and cordova-plugin-customurlscheme.",
[
"invalid-custom-token"
/* AuthErrorCode.INVALID_CUSTOM_TOKEN */
]: "The custom token format is incorrect. Please check the documentation.",
[
"invalid-dynamic-link-domain"
/* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */
]: "The provided dynamic link domain is not configured or authorized for the current project.",
[
"invalid-email"
/* AuthErrorCode.INVALID_EMAIL */
]: "The email address is badly formatted.",
[
"invalid-emulator-scheme"
/* AuthErrorCode.INVALID_EMULATOR_SCHEME */
]: "Emulator URL must start with a valid scheme (http:// or https://).",
[
"invalid-api-key"
/* AuthErrorCode.INVALID_API_KEY */
]: "Your API key is invalid, please check you have copied it correctly.",
[
"invalid-cert-hash"
/* AuthErrorCode.INVALID_CERT_HASH */
]: "The SHA-1 certificate hash provided is invalid.",
[
"invalid-credential"
/* AuthErrorCode.INVALID_CREDENTIAL */
]: "The supplied auth credential is incorrect, malformed or has expired.",
[
"invalid-message-payload"
/* AuthErrorCode.INVALID_MESSAGE_PAYLOAD */
]: "The email template corresponding to this action contains invalid characters in its message. Please fix by going to the Auth email templates section in the Firebase Console.",
[
"invalid-multi-factor-session"
/* AuthErrorCode.INVALID_MFA_SESSION */
]: "The request does not contain a valid proof of first factor successful sign-in.",
[
"invalid-oauth-provider"
/* AuthErrorCode.INVALID_OAUTH_PROVIDER */
]: "EmailAuthProvider is not supported for this operation. This operation only supports OAuth providers.",
[
"invalid-oauth-client-id"
/* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */
]: "The OAuth client ID provided is either invalid or does not match the specified API key.",
[
"unauthorized-domain"
/* AuthErrorCode.INVALID_ORIGIN */
]: "This domain is not authorized for OAuth operations for your Firebase project. Edit the list of authorized domains from the Firebase console.",
[
"invalid-action-code"
/* AuthErrorCode.INVALID_OOB_CODE */
]: "The action code is invalid. This can happen if the code is malformed, expired, or has already been used.",
[
"wrong-password"
/* AuthErrorCode.INVALID_PASSWORD */
]: "The password is invalid or the user does not have a password.",
[
"invalid-persistence-type"
/* AuthErrorCode.INVALID_PERSISTENCE */
]: "The specified persistence type is invalid. It can only be local, session or none.",
[
"invalid-phone-number"
/* AuthErrorCode.INVALID_PHONE_NUMBER */
]: "The format of the phone number provided is incorrect. Please enter the phone number in a format that can be parsed into E.164 format. E.164 phone numbers are written in the format [+][country code][subscriber number including area code].",
[
"invalid-provider-id"
/* AuthErrorCode.INVALID_PROVIDER_ID */
]: "The specified provider ID is invalid.",
[
"invalid-recipient-email"
/* AuthErrorCode.INVALID_RECIPIENT_EMAIL */
]: "The email corresponding to this action failed to send as the provided recipient email address is invalid.",
[
"invalid-sender"
/* AuthErrorCode.INVALID_SENDER */
]: "The email template corresponding to this action contains an invalid sender email or name. Please fix by going to the Auth email templates section in the Firebase Console.",
[
"invalid-verification-id"
/* AuthErrorCode.INVALID_SESSION_INFO */
]: "The verification ID used to create the phone auth credential is invalid.",
[
"invalid-tenant-id"
/* AuthErrorCode.INVALID_TENANT_ID */
]: "The Auth instance's tenant ID is invalid.",
[
"login-blocked"
/* AuthErrorCode.LOGIN_BLOCKED */
]: "Login blocked by user-provided method: {$originalMessage}",
[
"missing-android-pkg-name"
/* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
]: "An Android Package Name must be provided if the Android App is required to be installed.",
[
"auth-domain-config-required"
/* AuthErrorCode.MISSING_AUTH_DOMAIN */
]: "Be sure to include authDomain when calling firebase.initializeApp(), by following the instructions in the Firebase console.",
[
"missing-app-credential"
/* AuthErrorCode.MISSING_APP_CREDENTIAL */
]: "The phone verification request is missing an application verifier assertion. A reCAPTCHA response token needs to be provided.",
[
"missing-verification-code"
/* AuthErrorCode.MISSING_CODE */
]: "The phone auth credential was created with an empty SMS verification code.",
[
"missing-continue-uri"
/* AuthErrorCode.MISSING_CONTINUE_URI */
]: "A continue URL must be provided in the request.",
[
"missing-iframe-start"
/* AuthErrorCode.MISSING_IFRAME_START */
]: "An internal AuthError has occurred.",
[
"missing-ios-bundle-id"
/* AuthErrorCode.MISSING_IOS_BUNDLE_ID */
]: "An iOS Bundle ID must be provided if an App Store ID is provided.",
[
"missing-or-invalid-nonce"
/* AuthErrorCode.MISSING_OR_INVALID_NONCE */
]: "The request does not contain a valid nonce. This can occur if the SHA-256 hash of the provided raw nonce does not match the hashed nonce in the ID token payload.",
[
"missing-password"
/* AuthErrorCode.MISSING_PASSWORD */
]: "A non-empty password must be provided",
[
"missing-multi-factor-info"
/* AuthErrorCode.MISSING_MFA_INFO */
]: "No second factor identifier is provided.",
[
"missing-multi-factor-session"
/* AuthErrorCode.MISSING_MFA_SESSION */
]: "The request is missing proof of first factor successful sign-in.",
[
"missing-phone-number"
/* AuthErrorCode.MISSING_PHONE_NUMBER */
]: "To send verification codes, provide a phone number for the recipient.",
[
"missing-verification-id"
/* AuthErrorCode.MISSING_SESSION_INFO */
]: "The phone auth credential was created with an empty verification ID.",
[
"app-deleted"
/* AuthErrorCode.MODULE_DESTROYED */
]: "This instance of FirebaseApp has been deleted.",
[
"multi-factor-info-not-found"
/* AuthErrorCode.MFA_INFO_NOT_FOUND */
]: "The user does not have a second factor matching the identifier provided.",
[
"multi-factor-auth-required"
/* AuthErrorCode.MFA_REQUIRED */
]: "Proof of ownership of a second factor is required to complete sign-in.",
[
"account-exists-with-different-credential"
/* AuthErrorCode.NEED_CONFIRMATION */
]: "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.",
[
"network-request-failed"
/* AuthErrorCode.NETWORK_REQUEST_FAILED */
]: "A network AuthError (such as timeout, interrupted connection or unreachable host) has occurred.",
[
"no-auth-event"
/* AuthErrorCode.NO_AUTH_EVENT */
]: "An internal AuthError has occurred.",
[
"no-such-provider"
/* AuthErrorCode.NO_SUCH_PROVIDER */
]: "User was not linked to an account with the given provider.",
[
"null-user"
/* AuthErrorCode.NULL_USER */
]: "A null user object was provided as the argument for an operation which requires a non-null user object.",
[
"operation-not-allowed"
/* AuthErrorCode.OPERATION_NOT_ALLOWED */
]: "The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section.",
[
"operation-not-supported-in-this-environment"
/* AuthErrorCode.OPERATION_NOT_SUPPORTED */
]: 'This operation is not supported in the environment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled.',
[
"popup-blocked"
/* AuthErrorCode.POPUP_BLOCKED */
]: "Unable to establish a connection with the popup. It may have been blocked by the browser.",
[
"popup-closed-by-user"
/* AuthErrorCode.POPUP_CLOSED_BY_USER */
]: "The popup has been closed by the user before finalizing the operation.",
[
"provider-already-linked"
/* AuthErrorCode.PROVIDER_ALREADY_LINKED */
]: "User can only be linked to one identity for the given provider.",
[
"quota-exceeded"
/* AuthErrorCode.QUOTA_EXCEEDED */
]: "The project's quota for this operation has been exceeded.",
[
"redirect-cancelled-by-user"
/* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */
]: "The redirect operation has been cancelled by the user before finalizing.",
[
"redirect-operation-pending"
/* AuthErrorCode.REDIRECT_OPERATION_PENDING */
]: "A redirect sign-in operation is already pending.",
[
"rejected-credential"
/* AuthErrorCode.REJECTED_CREDENTIAL */
]: "The request contains malformed or mismatching credentials.",
[
"second-factor-already-in-use"
/* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */
]: "The second factor is already enrolled on this account.",
[
"maximum-second-factor-count-exceeded"
/* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */
]: "The maximum allowed number of second factors on a user has been exceeded.",
[
"tenant-id-mismatch"
/* AuthErrorCode.TENANT_ID_MISMATCH */
]: "The provided tenant ID does not match the Auth instance's tenant ID",
[
"timeout"
/* AuthErrorCode.TIMEOUT */
]: "The operation has timed out.",
[
"user-token-expired"
/* AuthErrorCode.TOKEN_EXPIRED */
]: "The user's credential is no longer valid. The user must sign in again.",
[
"too-many-requests"
/* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */
]: "We have blocked all requests from this device due to unusual activity. Try again later.",
[
"unauthorized-continue-uri"
/* AuthErrorCode.UNAUTHORIZED_DOMAIN */
]: "The domain of the continue URL is not whitelisted. Please whitelist the domain in the Firebase console.",
[
"unsupported-first-factor"
/* AuthErrorCode.UNSUPPORTED_FIRST_FACTOR */
]: "Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.",
[
"unsupported-persistence-type"
/* AuthErrorCode.UNSUPPORTED_PERSISTENCE */
]: "The current environment does not support the specified persistence type.",
[
"unsupported-tenant-operation"
/* AuthErrorCode.UNSUPPORTED_TENANT_OPERATION */
]: "This operation is not supported in a multi-tenant context.",
[
"unverified-email"
/* AuthErrorCode.UNVERIFIED_EMAIL */
]: "The operation requires a verified email.",
[
"user-cancelled"
/* AuthErrorCode.USER_CANCELLED */
]: "The user did not grant your application the permissions it requested.",
[
"user-not-found"
/* AuthErrorCode.USER_DELETED */
]: "There is no user record corresponding to this identifier. The user may have been deleted.",
[
"user-disabled"
/* AuthErrorCode.USER_DISABLED */
]: "The user account has been disabled by an administrator.",
[
"user-mismatch"
/* AuthErrorCode.USER_MISMATCH */
]: "The supplied credentials do not correspond to the previously signed in user.",
[
"user-signed-out"
/* AuthErrorCode.USER_SIGNED_OUT */
]: "",
[
"weak-password"
/* AuthErrorCode.WEAK_PASSWORD */
]: "The password must be 6 characters long or more.",
[
"web-storage-unsupported"
/* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */
]: "This browser is not supported or 3rd party cookies and data may be disabled.",
[
"already-initialized"
/* AuthErrorCode.ALREADY_INITIALIZED */
]: "initializeAuth() has already been called with different options. To avoid this error, call initializeAuth() with the same options as when it was originally called, or call getAuth() to return the already initialized instance.",
[
"missing-recaptcha-token"
/* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */
]: "The reCAPTCHA token is missing when sending request to the backend.",
[
"invalid-recaptcha-token"
/* AuthErrorCode.INVALID_RECAPTCHA_TOKEN */
]: "The reCAPTCHA token is invalid when sending request to the backend.",
[
"invalid-recaptcha-action"
/* AuthErrorCode.INVALID_RECAPTCHA_ACTION */
]: "The reCAPTCHA action is invalid when sending request to the backend.",
[
"recaptcha-not-enabled"
/* AuthErrorCode.RECAPTCHA_NOT_ENABLED */
]: "reCAPTCHA Enterprise integration is not enabled for this project.",
[
"missing-client-type"
/* AuthErrorCode.MISSING_CLIENT_TYPE */
]: "The reCAPTCHA client type is missing when sending request to the backend.",
[
"missing-recaptcha-version"
/* AuthErrorCode.MISSING_RECAPTCHA_VERSION */
]: "The reCAPTCHA version is missing when sending request to the backend.",
[
"invalid-req-type"
/* AuthErrorCode.INVALID_REQ_TYPE */
]: "Invalid request parameters.",
[
"invalid-recaptcha-version"
/* AuthErrorCode.INVALID_RECAPTCHA_VERSION */
]: "The reCAPTCHA version is invalid when sending request to the backend.",
[
"unsupported-password-policy-schema-version"
/* AuthErrorCode.UNSUPPORTED_PASSWORD_POLICY_SCHEMA_VERSION */
]: "The password policy received from the backend uses a schema version that is not supported by this version of the Firebase SDK.",
[
"password-does-not-meet-requirements"
/* AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */
]: "The password does not meet the requirements.",
[
"invalid-hosting-link-domain"
/* AuthErrorCode.INVALID_HOSTING_LINK_DOMAIN */
]: "The provided Hosting link domain is not configured in Firebase Hosting or is not owned by the current project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`)."
};
}
function _prodErrorMap() {
return {
[
"dependent-sdk-initialized-before-auth"
/* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
]: "Another Firebase SDK was initialized and is trying to use Auth before Auth is initialized. Please be sure to call `initializeAuth` or `getAuth` before starting any other Firebase SDK."
};
}
function _logWarn(msg, ...args) {
if (logClient.logLevel <= LogLevel.WARN) {
logClient.warn(`Auth (${SDK_VERSION}): ${msg}`, ...args);
}
}
function _logError(msg, ...args) {
if (logClient.logLevel <= LogLevel.ERROR) {
logClient.error(`Auth (${SDK_VERSION}): ${msg}`, ...args);
}
}
function _fail(authOrCode, ...rest) {
throw createErrorInternal(authOrCode, ...rest);
}
function _createError(authOrCode, ...rest) {
return createErrorInternal(authOrCode, ...rest);
}
function _errorWithCustomMessage(auth2, code, message) {
const errorMap = {
...prodErrorMap(),
[code]: message
};
const factory2 = new ErrorFactory("auth", "Firebase", errorMap);
return factory2.create(code, {
appName: auth2.name
});
}
function _serverAppCurrentUserOperationNotSupportedError(auth2) {
return _errorWithCustomMessage(auth2, "operation-not-supported-in-this-environment", "Operations that alter the current user are not supported in conjunction with FirebaseServerApp");
}
function createErrorInternal(authOrCode, ...rest) {
if (typeof authOrCode !== "string") {
const code = rest[0];
const fullParams = [...rest.slice(1)];
if (fullParams[0]) {
fullParams[0].appName = authOrCode.name;
}
return authOrCode._errorFactory.create(code, ...fullParams);
}
return _DEFAULT_AUTH_ERROR_FACTORY.create(authOrCode, ...rest);
}
function _assert(assertion, authOrCode, ...rest) {
if (!assertion) {
throw createErrorInternal(authOrCode, ...rest);
}
}
function debugFail(failure) {
const message = `INTERNAL ASSERTION FAILED: ` + failure;
_logError(message);
throw new Error(message);
}
function debugAssert(assertion, message) {
if (!assertion) {
debugFail(message);
}
}
function _getCurrentUrl() {
return typeof self !== "undefined" && self.location?.href || "";
}
function _isHttpOrHttps() {
return _getCurrentScheme() === "http:" || _getCurrentScheme() === "https:";
}
function _getCurrentScheme() {
return typeof self !== "undefined" && self.location?.protocol || null;
}
function _isOnline() {
if (typeof navigator !== "undefined" && navigator && "onLine" in navigator && typeof navigator.onLine === "boolean" && // Apply only for traditional web apps and Chrome extensions.
// This is especially true for Cordova apps which have unreliable
// navigator.onLine behavior unless cordova-plugin-network-information is
// installed which overwrites the native navigator.onLine value and
// defines navigator.connection.
(_isHttpOrHttps() || isBrowserExtension() || "connection" in navigator)) {
return navigator.onLine;
}
return true;
}
function _getUserLanguage() {
if (typeof navigator === "undefined") {
return null;
}
const navigatorLanguage = navigator;
return (
// Most reliable, but only supported in Chrome/Firefox.
navigatorLanguage.languages && navigatorLanguage.languages[0] || // Supported in most browsers, but returns the language of the browser
// UI, not the language set in browser settings.
navigatorLanguage.language || // Couldn't determine language.
null
);
}
function _emulatorUrl(config, path) {
debugAssert(config.emulator, "Emulator should always be set here");
const { url } = config.emulator;
if (!path) {
return url;
}
return `${url}${path.startsWith("/") ? path.slice(1) : path}`;
}
function _addTidIfNecessary(auth2, request) {
if (auth2.tenantId && !request.tenantId) {
return {
...request,
tenantId: auth2.tenantId
};
}
return request;
}
async function _performApiRequest(auth2, method, path, request, customErrorMap = {}) {
return _performFetchWithErrorHandling(auth2, customErrorMap, async () => {
let body = {};
let params = {};
if (request) {
if (method === "GET") {
params = request;
} else {
body = {
body: JSON.stringify(request)
};
}
}
const query = querystring({
key: auth2.config.apiKey,
...params
}).slice(1);
const headers = await auth2._getAdditionalHeaders();
headers[
"Content-Type"
/* HttpHeader.CONTENT_TYPE */
] = "application/json";
if (auth2.languageCode) {
headers[
"X-Firebase-Locale"
/* HttpHeader.X_FIREBASE_LOCALE */
] = auth2.languageCode;
}
const fetchArgs = {
method,
headers,
...body
};
if (!isCloudflareWorker()) {
fetchArgs.referrerPolicy = "no-referrer";
}
if (auth2.emulatorConfig && isCloudWorkstation(auth2.emulatorConfig.host)) {
fetchArgs.credentials = "include";
}
return FetchProvider.fetch()(await _getFinalTarget(auth2, auth2.config.apiHost, path, query), fetchArgs);
});
}
async function _performFetchWithErrorHandling(auth2, customErrorMap, fetchFn) {
auth2._canInitEmulator = false;
const errorMap = { ...SERVER_ERROR_MAP, ...customErrorMap };
try {
const networkTimeout = new NetworkTimeout(auth2);
const response = await Promise.race([
fetchFn(),
networkTimeout.promise
]);
networkTimeout.clearNetworkTimeout();
const json = await response.json();
if ("needConfirmation" in json) {
throw _makeTaggedError(auth2, "account-exists-with-different-credential", json);
}
if (response.ok && !("errorMessage" in json)) {
return json;
} else {
const errorMessage = response.ok ? json.errorMessage : json.error.message;
const [serverErrorCode, serverErrorMessage] = errorMessage.split(" : ");
if (serverErrorCode === "FEDERATED_USER_ID_ALREADY_LINKED") {
throw _makeTaggedError(auth2, "credential-already-in-use", json);
} else if (serverErrorCode === "EMAIL_EXISTS") {
throw _makeTaggedError(auth2, "email-already-in-use", json);
} else if (serverErrorCode === "USER_DISABLED") {
throw _makeTaggedError(auth2, "user-disabled", json);
}
const authError = errorMap[serverErrorCode] || serverErrorCode.toLowerCase().replace(/[_\s]+/g, "-");
if (serverErrorMessage) {
throw _errorWithCustomMessage(auth2, authError, serverErrorMessage);
} else {
_fail(auth2, authError);
}
}
} catch (e) {
if (e instanceof FirebaseError) {
throw e;
}
_fail(auth2, "network-request-failed", { "message": String(e) });
}
}
async function _performSignInRequest(auth2, method, path, request, customErrorMap = {}) {
const serverResponse = await _performApiRequest(auth2, method, path, request, customErrorMap);
if ("mfaPendingCredential" in serverResponse) {
_fail(auth2, "multi-factor-auth-required", {
_serverResponse: serverResponse
});
}
return serverResponse;
}
async function _getFinalTarget(auth2, host, path, query) {
const base = `${host}${path}?${query}`;
const authInternal = auth2;
const finalTarget = authInternal.config.emulator ? _emulatorUrl(auth2.config, base) : `${auth2.config.apiScheme}://${base}`;
if (CookieAuthProxiedEndpoints.includes(path)) {
await authInternal._persistenceManagerAvailable;
if (authInternal._getPersistenceType() === "COOKIE") {
const cookiePersistence = authInternal._getPersistence();
return cookiePersistence._getFinalTarget(finalTarget).toString();
}
}
return finalTarget;
}
function _parseEnforcementState(enforcementStateStr) {
switch (enforcementStateStr) {
case "ENFORCE":
return "ENFORCE";
case "AUDIT":
return "AUDIT";
case "OFF":
return "OFF";
default:
return "ENFORCEMENT_STATE_UNSPECIFIED";
}
}
function _makeTaggedError(auth2, code, response) {
const errorParams = {
appName: auth2.name
};
if (response.email) {
errorParams.email = response.email;
}
if (response.phoneNumber) {
errorParams.phoneNumber = response.phoneNumber;
}
const error = _createError(auth2, code, errorParams);
error.customData._tokenResponse = response;
return error;
}
function isEnterprise(grecaptcha) {
return grecaptcha !== void 0 && grecaptcha.enterprise !== void 0;
}
async function getRecaptchaConfig(auth2, request) {
return _performApiRequest(auth2, "GET", "/v2/recaptchaConfig", _addTidIfNecessary(auth2, request));
}
async function deleteAccount(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:delete", request);
}
async function deleteLinkedAccounts(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:update", request);
}
async function getAccountInfo(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:lookup", request);
}
function utcTimestampToDateString(utcTimestamp) {
if (!utcTimestamp) {
return void 0;
}
try {
const date = new Date(Number(utcTimestamp));
if (!isNaN(date.getTime())) {
return date.toUTCString();
}
} catch (e) {
}
return void 0;
}
function getIdToken(user, forceRefresh = false) {
return getModularInstance(user).getIdToken(forceRefresh);
}
async function getIdTokenResult(user, forceRefresh = false) {
const userInternal = getModularInstance(user);
const token = await userInternal.getIdToken(forceRefresh);
const claims = _parseToken(token);
_assert(
claims && claims.exp && claims.auth_time && claims.iat,
userInternal.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const firebase = typeof claims.firebase === "object" ? claims.firebase : void 0;
const signInProvider = firebase?.["sign_in_provider"];
return {
claims,
token,
authTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.auth_time)),
issuedAtTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.iat)),
expirationTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.exp)),
signInProvider: signInProvider || null,
signInSecondFactor: firebase?.["sign_in_second_factor"] || null
};
}
function secondsStringToMilliseconds(seconds) {
return Number(seconds) * 1e3;
}
function _parseToken(token) {
const [algorithm, payload, signature] = token.split(".");
if (algorithm === void 0 || payload === void 0 || signature === void 0) {
_logError("JWT malformed, contained fewer than 3 sections");
return null;
}
try {
const decoded = base64Decode(payload);
if (!decoded) {
_logError("Failed to decode base64 JWT payload");
return null;
}
return JSON.parse(decoded);
} catch (e) {
_logError("Caught error parsing JWT payload as JSON", e?.toString());
return null;
}
}
function _tokenExpiresIn(token) {
const parsedToken = _parseToken(token);
_assert(
parsedToken,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert(
typeof parsedToken.exp !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert(
typeof parsedToken.iat !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return Number(parsedToken.exp) - Number(parsedToken.iat);
}
async function _logoutIfInvalidated(user, promise, bypassAuthState = false) {
if (bypassAuthState) {
return promise;
}
try {
return await promise;
} catch (e) {
if (e instanceof FirebaseError && isUserInvalidated(e)) {
if (user.auth.currentUser === user) {
await user.auth.signOut();
}
}
throw e;
}
}
function isUserInvalidated({ code }) {
return code === `auth/${"user-disabled"}` || code === `auth/${"user-token-expired"}`;
}
async function _reloadWithoutSaving(user) {
const auth2 = user.auth;
const idToken = await user.getIdToken();
const response = await _logoutIfInvalidated(user, getAccountInfo(auth2, { idToken }));
_assert(
response?.users.length,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const coreAccount = response.users[0];
user._notifyReloadListener(coreAccount);
const newProviderData = coreAccount.providerUserInfo?.length ? extractProviderData(coreAccount.providerUserInfo) : [];
const providerData = mergeProviderData(user.providerData, newProviderData);
const oldIsAnonymous = user.isAnonymous;
const newIsAnonymous = !(user.email && coreAccount.passwordHash) && !providerData?.length;
const isAnonymous = !oldIsAnonymous ? false : newIsAnonymous;
const updates = {
uid: coreAccount.localId,
displayName: coreAccount.displayName || null,
photoURL: coreAccount.photoUrl || null,
email: coreAccount.email || null,
emailVerified: coreAccount.emailVerified || false,
phoneNumber: coreAccount.phoneNumber || null,
tenantId: coreAccount.tenantId || null,
providerData,
metadata: new UserMetadata(coreAccount.createdAt, coreAccount.lastLoginAt),
isAnonymous
};
Object.assign(user, updates);
}
async function reload(user) {
const userInternal = getModularInstance(user);
await _reloadWithoutSaving(userInternal);
await userInternal.auth._persistUserIfCurrent(userInternal);
userInternal.auth._notifyListenersIfCurrent(userInternal);
}
function mergeProviderData(original, newData) {
const deduped = original.filter((o) => !newData.some((n) => n.providerId === o.providerId));
return [...deduped, ...newData];
}
function extractProviderData(providers) {
return providers.map(({ providerId, ...provider }) => {
return {
providerId,
uid: provider.rawId || "",
displayName: provider.displayName || null,
email: provider.email || null,
phoneNumber: provider.phoneNumber || null,
photoURL: provider.photoUrl || null
};
});
}
async function requestStsToken(auth2, refreshToken) {
const response = await _performFetchWithErrorHandling(auth2, {}, async () => {
const body = querystring({
"grant_type": "refresh_token",
"refresh_token": refreshToken
}).slice(1);
const { tokenApiHost, apiKey } = auth2.config;
const url = await _getFinalTarget(auth2, tokenApiHost, "/v1/token", `key=${apiKey}`);
const headers = await auth2._getAdditionalHeaders();
headers[
"Content-Type"
/* HttpHeader.CONTENT_TYPE */
] = "application/x-www-form-urlencoded";
const options = {
method: "POST",
headers,
body
};
if (auth2.emulatorConfig && isCloudWorkstation(auth2.emulatorConfig.host)) {
options.credentials = "include";
}
return FetchProvider.fetch()(url, options);
});
return {
accessToken: response.access_token,
expiresIn: response.expires_in,
refreshToken: response.refresh_token
};
}
async function revokeToken(auth2, request) {
return _performApiRequest(auth2, "POST", "/v2/accounts:revokeToken", _addTidIfNecessary(auth2, request));
}
function assertStringOrUndefined(assertion, appName) {
_assert(typeof assertion === "string" || typeof assertion === "undefined", "internal-error", { appName });
}
function _getInstance(cls) {
debugAssert(cls instanceof Function, "Expected a class definition");
let instance = instanceCache.get(cls);
if (instance) {
debugAssert(instance instanceof cls, "Instance stored in cache mismatched with class");
return instance;
}
instance = new cls();
instanceCache.set(cls, instance);
return instance;
}
function _persistenceKeyName(key, apiKey, appName) {
return `${"firebase"}:${key}:${apiKey}:${appName}`;
}
function _getBrowserName(userAgent) {
const ua = userAgent.toLowerCase();
if (ua.includes("opera/") || ua.includes("opr/") || ua.includes("opios/")) {
return "Opera";
} else if (_isIEMobile(ua)) {
return "IEMobile";
} else if (ua.includes("msie") || ua.includes("trident/")) {
return "IE";
} else if (ua.includes("edge/")) {
return "Edge";
} else if (_isFirefox(ua)) {
return "Firefox";
} else if (ua.includes("silk/")) {
return "Silk";
} else if (_isBlackBerry(ua)) {
return "Blackberry";
} else if (_isWebOS(ua)) {
return "Webos";
} else if (_isSafari(ua)) {
return "Safari";
} else if ((ua.includes("chrome/") || _isChromeIOS(ua)) && !ua.includes("edge/")) {
return "Chrome";
} else if (_isAndroid(ua)) {
return "Android";
} else {
const re = /([a-zA-Z\d\.]+)\/[a-zA-Z\d\.]*$/;
const matches = userAgent.match(re);
if (matches?.length === 2) {
return matches[1];
}
}
return "Other";
}
function _isFirefox(ua = getUA()) {
return /firefox\//i.test(ua);
}
function _isSafari(userAgent = getUA()) {
const ua = userAgent.toLowerCase();
return ua.includes("safari/") && !ua.includes("chrome/") && !ua.includes("crios/") && !ua.includes("android");
}
function _isChromeIOS(ua = getUA()) {
return /crios\//i.test(ua);
}
function _isIEMobile(ua = getUA()) {
return /iemobile/i.test(ua);
}
function _isAndroid(ua = getUA()) {
return /android/i.test(ua);
}
function _isBlackBerry(ua = getUA()) {
return /blackberry/i.test(ua);
}
function _isWebOS(ua = getUA()) {
return /webos/i.test(ua);
}
function _getClientVersion(clientPlatform, frameworks = []) {
let reportedPlatform;
switch (clientPlatform) {
case "Browser":
reportedPlatform = _getBrowserName(getUA());
break;
case "Worker":
reportedPlatform = `${_getBrowserName(getUA())}-${clientPlatform}`;
break;
default:
reportedPlatform = clientPlatform;
}
const reportedFrameworks = frameworks.length ? frameworks.join(",") : "FirebaseCore-web";
return `${reportedPlatform}/${"JsCore"}/${SDK_VERSION}/${reportedFrameworks}`;
}
async function _getPasswordPolicy(auth2, request = {}) {
return _performApiRequest(auth2, "GET", "/v2/passwordPolicy", _addTidIfNecessary(auth2, request));
}
function _castAuth(auth2) {
return getModularInstance(auth2);
}
function _loadJS(url) {
return externalJSProvider.loadJS(url);
}
function _recaptchaEnterpriseScriptUrl() {
return externalJSProvider.recaptchaEnterpriseScript;
}
async function injectRecaptchaFields(auth2, request, action, isCaptchaResp = false, isFakeToken = false) {
const verifier = new RecaptchaEnterpriseVerifier(auth2);
let captchaResponse;
if (isFakeToken) {
captchaResponse = FAKE_TOKEN;
} else {
try {
captchaResponse = await verifier.verify(action);
} catch (error) {
captchaResponse = await verifier.verify(action, true);
}
}
const newRequest = { ...request };
if (action === "mfaSmsEnrollment" || action === "mfaSmsSignIn") {
if ("phoneEnrollmentInfo" in newRequest) {
const phoneNumber = newRequest.phoneEnrollmentInfo.phoneNumber;
const recaptchaToken = newRequest.phoneEnrollmentInfo.recaptchaToken;
Object.assign(newRequest, {
"phoneEnrollmentInfo": {
phoneNumber,
recaptchaToken,
captchaResponse,
"clientType": "CLIENT_TYPE_WEB",
"recaptchaVersion": "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
}
});
} else if ("phoneSignInInfo" in newRequest) {
const recaptchaToken = newRequest.phoneSignInInfo.recaptchaToken;
Object.assign(newRequest, {
"phoneSignInInfo": {
recaptchaToken,
captchaResponse,
"clientType": "CLIENT_TYPE_WEB",
"recaptchaVersion": "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
}
});
}
return newRequest;
}
if (!isCaptchaResp) {
Object.assign(newRequest, { captchaResponse });
} else {
Object.assign(newRequest, { "captchaResp": captchaResponse });
}
Object.assign(newRequest, {
"clientType": "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
});
Object.assign(newRequest, {
"recaptchaVersion": "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
});
return newRequest;
}
async function handleRecaptchaFlow(authInstance, request, actionName, actionMethod, recaptchaAuthProvider) {
if (recaptchaAuthProvider === "EMAIL_PASSWORD_PROVIDER") {
if (authInstance._getRecaptchaConfig()?.isProviderEnabled(
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
)) {
const requestWithRecaptcha = await injectRecaptchaFields(
authInstance,
request,
actionName,
actionName === "getOobCode"
/* RecaptchaActionName.GET_OOB_CODE */
);
return actionMethod(authInstance, requestWithRecaptcha);
} else {
return actionMethod(authInstance, request).catch(async (error) => {
if (error.code === `auth/${"missing-recaptcha-token"}`) {
console.log(`${actionName} is protected by reCAPTCHA Enterprise for this project. Automatically triggering the reCAPTCHA flow and restarting the flow.`);
const requestWithRecaptcha = await injectRecaptchaFields(
authInstance,
request,
actionName,
actionName === "getOobCode"
/* RecaptchaActionName.GET_OOB_CODE */
);
return actionMethod(authInstance, requestWithRecaptcha);
} else {
return Promise.reject(error);
}
});
}
} else if (recaptchaAuthProvider === "PHONE_PROVIDER") {
if (authInstance._getRecaptchaConfig()?.isProviderEnabled(
"PHONE_PROVIDER"
/* RecaptchaAuthProvider.PHONE_PROVIDER */
)) {
const requestWithRecaptcha = await injectRecaptchaFields(authInstance, request, actionName);
return actionMethod(authInstance, requestWithRecaptcha).catch(async (error) => {
if (authInstance._getRecaptchaConfig()?.getProviderEnforcementState(
"PHONE_PROVIDER"
/* RecaptchaAuthProvider.PHONE_PROVIDER */
) === "AUDIT") {
if (error.code === `auth/${"missing-recaptcha-token"}` || error.code === `auth/${"invalid-app-credential"}`) {
console.log(`Failed to verify with reCAPTCHA Enterprise. Automatically triggering the reCAPTCHA v2 flow to complete the ${actionName} flow.`);
const requestWithRecaptchaFields = await injectRecaptchaFields(
authInstance,
request,
actionName,
false,
// isCaptchaResp
true
// isFakeToken
);
return actionMethod(authInstance, requestWithRecaptchaFields);
}
}
return Promise.reject(error);
});
} else {
const requestWithRecaptchaFields = await injectRecaptchaFields(
authInstance,
request,
actionName,
false,
// isCaptchaResp
true
// isFakeToken
);
return actionMethod(authInstance, requestWithRecaptchaFields);
}
} else {
return Promise.reject(recaptchaAuthProvider + " provider is not supported.");
}
}
async function _initializeRecaptchaConfig(auth2) {
const authInternal = _castAuth(auth2);
const response = await getRecaptchaConfig(authInternal, {
clientType: "CLIENT_TYPE_WEB",
version: "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
});
const config = new RecaptchaConfig(response);
if (authInternal.tenantId == null) {
authInternal._agentRecaptchaConfig = config;
} else {
authInternal._tenantRecaptchaConfigs[authInternal.tenantId] = config;
}
if (config.isAnyProviderEnabled()) {
const verifier = new RecaptchaEnterpriseVerifier(authInternal);
void verifier.verify();
}
}
function initializeAuth(app2, deps) {
const provider = _getProvider(app2, "auth");
if (provider.isInitialized()) {
const auth3 = provider.getImmediate();
const initialOptions = provider.getOptions();
if (deepEqual(initialOptions, deps ?? {})) {
return auth3;
} else {
_fail(
auth3,
"already-initialized"
/* AuthErrorCode.ALREADY_INITIALIZED */
);
}
}
const auth2 = provider.initialize({ options: deps });
return auth2;
}
function _initializeAuthInstance(auth2, deps) {
const persistence = deps?.persistence || [];
const hierarchy = (Array.isArray(persistence) ? persistence : [persistence]).map(_getInstance);
if (deps?.errorMap) {
auth2._updateErrorMap(deps.errorMap);
}
auth2._initializeWithPersistence(hierarchy, deps?.popupRedirectResolver);
}
function connectAuthEmulator(auth2, url, options) {
const authInternal = _castAuth(auth2);
_assert(
/^https?:\/\//.test(url),
authInternal,
"invalid-emulator-scheme"
/* AuthErrorCode.INVALID_EMULATOR_SCHEME */
);
const disableWarnings = !!options?.disableWarnings;
const protocol = extractProtocol(url);
const { host, port } = extractHostAndPort(url);
const portStr = port === null ? "" : `:${port}`;
const emulator = { url: `${protocol}//${host}${portStr}/` };
const emulatorConfig = Object.freeze({
host,
port,
protocol: protocol.replace(":", ""),
options: Object.freeze({ disableWarnings })
});
if (!authInternal._canInitEmulator) {
_assert(
authInternal.config.emulator && authInternal.emulatorConfig,
authInternal,
"emulator-config-failed"
/* AuthErrorCode.EMULATOR_CONFIG_FAILED */
);
_assert(
deepEqual(emulator, authInternal.config.emulator) && deepEqual(emulatorConfig, authInternal.emulatorConfig),
authInternal,
"emulator-config-failed"
/* AuthErrorCode.EMULATOR_CONFIG_FAILED */
);
return;
}
authInternal.config.emulator = emulator;
authInternal.emulatorConfig = emulatorConfig;
authInternal.settings.appVerificationDisabledForTesting = true;
if (isCloudWorkstation(host)) {
void pingServer(`${protocol}//${host}${portStr}`);
updateEmulatorBanner("Auth", true);
} else if (!disableWarnings) {
emitEmulatorWarning();
}
}
function extractProtocol(url) {
const protocolEnd = url.indexOf(":");
return protocolEnd < 0 ? "" : url.substr(0, protocolEnd + 1);
}
function extractHostAndPort(url) {
const protocol = extractProtocol(url);
const authority = /(\/\/)?([^?#/]+)/.exec(url.substr(protocol.length));
if (!authority) {
return { host: "", port: null };
}
const hostAndPort = authority[2].split("@").pop() || "";
const bracketedIPv6 = /^(\[[^\]]+\])(:|$)/.exec(hostAndPort);
if (bracketedIPv6) {
const host = bracketedIPv6[1];
return { host, port: parsePort(hostAndPort.substr(host.length + 1)) };
} else {
const [host, port] = hostAndPort.split(":");
return { host, port: parsePort(port) };
}
}
function parsePort(portStr) {
if (!portStr) {
return null;
}
const port = Number(portStr);
if (isNaN(port)) {
return null;
}
return port;
}
function emitEmulatorWarning() {
function attachBanner() {
const el = document.createElement("p");
const sty = el.style;
el.innerText = "Running in emulator mode. Do not use with production credentials.";
sty.position = "fixed";
sty.width = "100%";
sty.backgroundColor = "#ffffff";
sty.border = ".1em solid #000000";
sty.color = "#b50000";
sty.bottom = "0px";
sty.left = "0px";
sty.margin = "0px";
sty.zIndex = "10000";
sty.textAlign = "center";
el.classList.add("firebase-emulator-warning");
document.body.appendChild(el);
}
if (typeof console !== "undefined" && typeof console.info === "function") {
console.info("WARNING: You are using the Auth Emulator, which is intended for local testing only. Do not use with production credentials.");
}
if (typeof window !== "undefined" && typeof document !== "undefined") {
if (document.readyState === "loading") {
window.addEventListener("DOMContentLoaded", attachBanner);
} else {
attachBanner();
}
}
}
async function resetPassword(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:resetPassword", _addTidIfNecessary(auth2, request));
}
async function updateEmailPassword(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:update", request);
}
async function linkEmailPassword(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:signUp", request);
}
async function applyActionCode$1(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:update", _addTidIfNecessary(auth2, request));
}
async function signInWithPassword(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithPassword", _addTidIfNecessary(auth2, request));
}
async function sendOobCode(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:sendOobCode", _addTidIfNecessary(auth2, request));
}
async function sendEmailVerification$1(auth2, request) {
return sendOobCode(auth2, request);
}
async function sendPasswordResetEmail$1(auth2, request) {
return sendOobCode(auth2, request);
}
async function sendSignInLinkToEmail$1(auth2, request) {
return sendOobCode(auth2, request);
}
async function verifyAndChangeEmail(auth2, request) {
return sendOobCode(auth2, request);
}
async function signInWithEmailLink$1(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithEmailLink", _addTidIfNecessary(auth2, request));
}
async function signInWithEmailLinkForLinking(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithEmailLink", _addTidIfNecessary(auth2, request));
}
async function signInWithIdp(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithIdp", _addTidIfNecessary(auth2, request));
}
async function signInWithPhoneNumber$1(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithPhoneNumber", _addTidIfNecessary(auth2, request));
}
async function linkWithPhoneNumber$1(auth2, request) {
const response = await _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithPhoneNumber", _addTidIfNecessary(auth2, request));
if (response.temporaryProof) {
throw _makeTaggedError(auth2, "account-exists-with-different-credential", response);
}
return response;
}
async function verifyPhoneNumberForExisting(auth2, request) {
const apiRequest = {
...request,
operation: "REAUTH"
};
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithPhoneNumber", _addTidIfNecessary(auth2, apiRequest), VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_);
}
function parseMode(mode) {
switch (mode) {
case "recoverEmail":
return "RECOVER_EMAIL";
case "resetPassword":
return "PASSWORD_RESET";
case "signIn":
return "EMAIL_SIGNIN";
case "verifyEmail":
return "VERIFY_EMAIL";
case "verifyAndChangeEmail":
return "VERIFY_AND_CHANGE_EMAIL";
case "revertSecondFactorAddition":
return "REVERT_SECOND_FACTOR_ADDITION";
default:
return null;
}
}
function parseDeepLink(url) {
const link = querystringDecode(extractQuerystring(url))["link"];
const doubleDeepLink = link ? querystringDecode(extractQuerystring(link))["deep_link_id"] : null;
const iOSDeepLink = querystringDecode(extractQuerystring(url))["deep_link_id"];
const iOSDoubleDeepLink = iOSDeepLink ? querystringDecode(extractQuerystring(iOSDeepLink))["link"] : null;
return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
}
function parseActionCodeURL(link) {
return ActionCodeURL.parseLink(link);
}
async function signUp(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signUp", _addTidIfNecessary(auth2, request));
}
function providerIdForResponse(response) {
if (response.providerId) {
return response.providerId;
}
if ("phoneNumber" in response) {
return "phone";
}
return null;
}
async function signInAnonymously(auth2) {
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
const authInternal = _castAuth(auth2);
await authInternal._initializationPromise;
if (authInternal.currentUser?.isAnonymous) {
return new UserCredentialImpl({
user: authInternal.currentUser,
providerId: null,
operationType: "signIn"
/* OperationType.SIGN_IN */
});
}
const response = await signUp(authInternal, {
returnSecureToken: true
});
const userCredential = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn", response, true);
await authInternal._updateCurrentUser(userCredential.user);
return userCredential;
}
function _processCredentialSavingMfaContextIfNecessary(auth2, operationType, credential, user) {
const idTokenProvider = operationType === "reauthenticate" ? credential._getReauthenticationResolver(auth2) : credential._getIdTokenResponse(auth2);
return idTokenProvider.catch((error) => {
if (error.code === `auth/${"multi-factor-auth-required"}`) {
throw MultiFactorError._fromErrorAndOperation(auth2, error, operationType, user);
}
throw error;
});
}
function providerDataAsNames(providerData) {
return new Set(providerData.map(({ providerId }) => providerId).filter((pid) => !!pid));
}
async function unlink(user, providerId) {
const userInternal = getModularInstance(user);
await _assertLinkedStatus(true, userInternal, providerId);
const { providerUserInfo } = await deleteLinkedAccounts(userInternal.auth, {
idToken: await userInternal.getIdToken(),
deleteProvider: [providerId]
});
const providersLeft = providerDataAsNames(providerUserInfo || []);
userInternal.providerData = userInternal.providerData.filter((pd) => providersLeft.has(pd.providerId));
if (!providersLeft.has(
"phone"
/* ProviderId.PHONE */
)) {
userInternal.phoneNumber = null;
}
await userInternal.auth._persistUserIfCurrent(userInternal);
return userInternal;
}
async function _link(user, credential, bypassAuthState = false) {
const response = await _logoutIfInvalidated(user, credential._linkToIdToken(user.auth, await user.getIdToken()), bypassAuthState);
return UserCredentialImpl._forOperation(user, "link", response);
}
async function _assertLinkedStatus(expected, user, provider) {
await _reloadWithoutSaving(user);
const providerIds = providerDataAsNames(user.providerData);
const code = expected === false ? "provider-already-linked" : "no-such-provider";
_assert(providerIds.has(provider) === expected, user.auth, code);
}
async function _reauthenticate(user, credential, bypassAuthState = false) {
const { auth: auth2 } = user;
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
const operationType = "reauthenticate";
try {
const response = await _logoutIfInvalidated(user, _processCredentialSavingMfaContextIfNecessary(auth2, operationType, credential, user), bypassAuthState);
_assert(
response.idToken,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const parsed = _parseToken(response.idToken);
_assert(
parsed,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const { sub: localId } = parsed;
_assert(
user.uid === localId,
auth2,
"user-mismatch"
/* AuthErrorCode.USER_MISMATCH */
);
return UserCredentialImpl._forOperation(user, operationType, response);
} catch (e) {
if (e?.code === `auth/${"user-not-found"}`) {
_fail(
auth2,
"user-mismatch"
/* AuthErrorCode.USER_MISMATCH */
);
}
throw e;
}
}
async function _signInWithCredential(auth2, credential, bypassAuthState = false) {
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
const operationType = "signIn";
const response = await _processCredentialSavingMfaContextIfNecessary(auth2, operationType, credential);
const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth2, operationType, response);
if (!bypassAuthState) {
await auth2._updateCurrentUser(userCredential.user);
}
return userCredential;
}
async function signInWithCredential(auth2, credential) {
return _signInWithCredential(_castAuth(auth2), credential);
}
async function linkWithCredential(user, credential) {
const userInternal = getModularInstance(user);
await _assertLinkedStatus(false, userInternal, credential.providerId);
return _link(userInternal, credential);
}
async function reauthenticateWithCredential(user, credential) {
return _reauthenticate(getModularInstance(user), credential);
}
async function signInWithCustomToken$1(auth2, request) {
return _performSignInRequest(auth2, "POST", "/v1/accounts:signInWithCustomToken", _addTidIfNecessary(auth2, request));
}
async function signInWithCustomToken(auth2, customToken) {
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
const authInternal = _castAuth(auth2);
const response = await signInWithCustomToken$1(authInternal, {
token: customToken,
returnSecureToken: true
});
const cred = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn", response);
await authInternal._updateCurrentUser(cred.user);
return cred;
}
function _setActionCodeSettingsOnRequest(auth2, request, actionCodeSettings) {
_assert(
actionCodeSettings.url?.length > 0,
auth2,
"invalid-continue-uri"
/* AuthErrorCode.INVALID_CONTINUE_URI */
);
_assert(
typeof actionCodeSettings.dynamicLinkDomain === "undefined" || actionCodeSettings.dynamicLinkDomain.length > 0,
auth2,
"invalid-dynamic-link-domain"
/* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */
);
_assert(
typeof actionCodeSettings.linkDomain === "undefined" || actionCodeSettings.linkDomain.length > 0,
auth2,
"invalid-hosting-link-domain"
/* AuthErrorCode.INVALID_HOSTING_LINK_DOMAIN */
);
request.continueUrl = actionCodeSettings.url;
request.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
request.linkDomain = actionCodeSettings.linkDomain;
request.canHandleCodeInApp = actionCodeSettings.handleCodeInApp;
if (actionCodeSettings.iOS) {
_assert(
actionCodeSettings.iOS.bundleId.length > 0,
auth2,
"missing-ios-bundle-id"
/* AuthErrorCode.MISSING_IOS_BUNDLE_ID */
);
request.iOSBundleId = actionCodeSettings.iOS.bundleId;
}
if (actionCodeSettings.android) {
_assert(
actionCodeSettings.android.packageName.length > 0,
auth2,
"missing-android-pkg-name"
/* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
);
request.androidInstallApp = actionCodeSettings.android.installApp;
request.androidMinimumVersionCode = actionCodeSettings.android.minimumVersion;
request.androidPackageName = actionCodeSettings.android.packageName;
}
}
async function recachePasswordPolicy(auth2) {
const authInternal = _castAuth(auth2);
if (authInternal._getPasswordPolicyInternal()) {
await authInternal._updatePasswordPolicy();
}
}
async function sendPasswordResetEmail(auth2, email, actionCodeSettings) {
const authInternal = _castAuth(auth2);
const request = {
requestType: "PASSWORD_RESET",
email,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
if (actionCodeSettings) {
_setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
}
await handleRecaptchaFlow(
authInternal,
request,
"getOobCode",
sendPasswordResetEmail$1,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
}
async function confirmPasswordReset(auth2, oobCode, newPassword) {
await resetPassword(getModularInstance(auth2), {
oobCode,
newPassword
}).catch(async (error) => {
if (error.code === `auth/${"password-does-not-meet-requirements"}`) {
void recachePasswordPolicy(auth2);
}
throw error;
});
}
async function applyActionCode(auth2, oobCode) {
await applyActionCode$1(getModularInstance(auth2), { oobCode });
}
async function checkActionCode(auth2, oobCode) {
const authModular = getModularInstance(auth2);
const response = await resetPassword(authModular, { oobCode });
const operation = response.requestType;
_assert(
operation,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
switch (operation) {
case "EMAIL_SIGNIN":
break;
case "VERIFY_AND_CHANGE_EMAIL":
_assert(
response.newEmail,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
break;
case "REVERT_SECOND_FACTOR_ADDITION":
_assert(
response.mfaInfo,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
// fall through
default:
_assert(
response.email,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
let multiFactorInfo = null;
if (response.mfaInfo) {
multiFactorInfo = MultiFactorInfoImpl._fromServerResponse(_castAuth(authModular), response.mfaInfo);
}
return {
data: {
email: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" ? response.newEmail : response.email) || null,
previousEmail: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" ? response.email : response.newEmail) || null,
multiFactorInfo
},
operation
};
}
async function verifyPasswordResetCode(auth2, code) {
const { data } = await checkActionCode(getModularInstance(auth2), code);
return data.email;
}
async function createUserWithEmailAndPassword(auth2, email, password) {
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
const authInternal = _castAuth(auth2);
const request = {
returnSecureToken: true,
email,
password,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
const signUpResponse = handleRecaptchaFlow(
authInternal,
request,
"signUpPassword",
signUp,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
const response = await signUpResponse.catch((error) => {
if (error.code === `auth/${"password-does-not-meet-requirements"}`) {
void recachePasswordPolicy(auth2);
}
throw error;
});
const userCredential = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn", response);
await authInternal._updateCurrentUser(userCredential.user);
return userCredential;
}
function signInWithEmailAndPassword(auth2, email, password) {
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
return signInWithCredential(getModularInstance(auth2), EmailAuthProvider.credential(email, password)).catch(async (error) => {
if (error.code === `auth/${"password-does-not-meet-requirements"}`) {
void recachePasswordPolicy(auth2);
}
throw error;
});
}
async function sendSignInLinkToEmail(auth2, email, actionCodeSettings) {
const authInternal = _castAuth(auth2);
const request = {
requestType: "EMAIL_SIGNIN",
email,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
function setActionCodeSettings(request2, actionCodeSettings2) {
_assert(
actionCodeSettings2.handleCodeInApp,
authInternal,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
if (actionCodeSettings2) {
_setActionCodeSettingsOnRequest(authInternal, request2, actionCodeSettings2);
}
}
setActionCodeSettings(request, actionCodeSettings);
await handleRecaptchaFlow(
authInternal,
request,
"getOobCode",
sendSignInLinkToEmail$1,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
}
function isSignInWithEmailLink(auth2, emailLink) {
const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
return actionCodeUrl?.operation === "EMAIL_SIGNIN";
}
async function signInWithEmailLink(auth2, email, emailLink) {
if (_isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(auth2));
}
const authModular = getModularInstance(auth2);
const credential = EmailAuthProvider.credentialWithLink(email, emailLink || _getCurrentUrl());
_assert(
credential._tenantId === (authModular.tenantId || null),
authModular,
"tenant-id-mismatch"
/* AuthErrorCode.TENANT_ID_MISMATCH */
);
return signInWithCredential(authModular, credential);
}
async function createAuthUri(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:createAuthUri", _addTidIfNecessary(auth2, request));
}
async function fetchSignInMethodsForEmail(auth2, email) {
const continueUri = _isHttpOrHttps() ? _getCurrentUrl() : "http://localhost";
const request = {
identifier: email,
continueUri
};
const { signinMethods } = await createAuthUri(getModularInstance(auth2), request);
return signinMethods || [];
}
async function sendEmailVerification(user, actionCodeSettings) {
const userInternal = getModularInstance(user);
const idToken = await user.getIdToken();
const request = {
requestType: "VERIFY_EMAIL",
idToken
};
if (actionCodeSettings) {
_setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
}
const { email } = await sendEmailVerification$1(userInternal.auth, request);
if (email !== user.email) {
await user.reload();
}
}
async function verifyBeforeUpdateEmail(user, newEmail, actionCodeSettings) {
const userInternal = getModularInstance(user);
const idToken = await user.getIdToken();
const request = {
requestType: "VERIFY_AND_CHANGE_EMAIL",
idToken,
newEmail
};
if (actionCodeSettings) {
_setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
}
const { email } = await verifyAndChangeEmail(userInternal.auth, request);
if (email !== user.email) {
await user.reload();
}
}
async function updateProfile$1(auth2, request) {
return _performApiRequest(auth2, "POST", "/v1/accounts:update", request);
}
async function updateProfile(user, { displayName, photoURL: photoUrl }) {
if (displayName === void 0 && photoUrl === void 0) {
return;
}
const userInternal = getModularInstance(user);
const idToken = await userInternal.getIdToken();
const profileRequest = {
idToken,
displayName,
photoUrl,
returnSecureToken: true
};
const response = await _logoutIfInvalidated(userInternal, updateProfile$1(userInternal.auth, profileRequest));
userInternal.displayName = response.displayName || null;
userInternal.photoURL = response.photoUrl || null;
const passwordProvider = userInternal.providerData.find(
({ providerId }) => providerId === "password"
/* ProviderId.PASSWORD */
);
if (passwordProvider) {
passwordProvider.displayName = userInternal.displayName;
passwordProvider.photoURL = userInternal.photoURL;
}
await userInternal._updateTokensIfNecessary(response);
}
function updateEmail(user, newEmail) {
const userInternal = getModularInstance(user);
if (_isFirebaseServerApp(userInternal.auth.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(userInternal.auth));
}
return updateEmailOrPassword(userInternal, newEmail, null);
}
function updatePassword(user, newPassword) {
return updateEmailOrPassword(getModularInstance(user), null, newPassword);
}
async function updateEmailOrPassword(user, email, password) {
const { auth: auth2 } = user;
const idToken = await user.getIdToken();
const request = {
idToken,
returnSecureToken: true
};
if (email) {
request.email = email;
}
if (password) {
request.password = password;
}
const response = await _logoutIfInvalidated(user, updateEmailPassword(auth2, request));
await user._updateTokensIfNecessary(
response,
/* reload */
true
);
}
function _fromIdTokenResponse(idTokenResponse) {
if (!idTokenResponse) {
return null;
}
const { providerId } = idTokenResponse;
const profile = idTokenResponse.rawUserInfo ? JSON.parse(idTokenResponse.rawUserInfo) : {};
const isNewUser = idTokenResponse.isNewUser || idTokenResponse.kind === "identitytoolkit#SignupNewUserResponse";
if (!providerId && idTokenResponse?.idToken) {
const signInProvider = _parseToken(idTokenResponse.idToken)?.firebase?.["sign_in_provider"];
if (signInProvider) {
const filteredProviderId = signInProvider !== "anonymous" && signInProvider !== "custom" ? signInProvider : null;
return new GenericAdditionalUserInfo(isNewUser, filteredProviderId);
}
}
if (!providerId) {
return null;
}
switch (providerId) {
case "facebook.com":
return new FacebookAdditionalUserInfo(isNewUser, profile);
case "github.com":
return new GithubAdditionalUserInfo(isNewUser, profile);
case "google.com":
return new GoogleAdditionalUserInfo(isNewUser, profile);
case "twitter.com":
return new TwitterAdditionalUserInfo(isNewUser, profile, idTokenResponse.screenName || null);
case "custom":
case "anonymous":
return new GenericAdditionalUserInfo(isNewUser, null);
default:
return new GenericAdditionalUserInfo(isNewUser, providerId, profile);
}
}
function getAdditionalUserInfo(userCredential) {
const { user, _tokenResponse } = userCredential;
if (user.isAnonymous && !_tokenResponse) {
return {
providerId: null,
isNewUser: false,
profile: null
};
}
return _fromIdTokenResponse(_tokenResponse);
}
function setPersistence(auth2, persistence) {
return getModularInstance(auth2).setPersistence(persistence);
}
function initializeRecaptchaConfig(auth2) {
return _initializeRecaptchaConfig(auth2);
}
async function validatePassword(auth2, password) {
const authInternal = _castAuth(auth2);
return authInternal.validatePassword(password);
}
function onIdTokenChanged(auth2, nextOrObserver, error, completed) {
return getModularInstance(auth2).onIdTokenChanged(nextOrObserver, error, completed);
}
function beforeAuthStateChanged(auth2, callback, onAbort) {
return getModularInstance(auth2).beforeAuthStateChanged(callback, onAbort);
}
function onAuthStateChanged(auth2, nextOrObserver, error, completed) {
return getModularInstance(auth2).onAuthStateChanged(nextOrObserver, error, completed);
}
function useDeviceLanguage(auth2) {
getModularInstance(auth2).useDeviceLanguage();
}
function updateCurrentUser(auth2, user) {
return getModularInstance(auth2).updateCurrentUser(user);
}
function signOut(auth2) {
return getModularInstance(auth2).signOut();
}
function revokeAccessToken(auth2, token) {
const authInternal = _castAuth(auth2);
return authInternal.revokeAccessToken(token);
}
async function deleteUser(user) {
return getModularInstance(user).delete();
}
function getMultiFactorResolver(auth2, error) {
const authModular = getModularInstance(auth2);
const errorInternal = error;
_assert(
error.customData.operationType,
authModular,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
_assert(
errorInternal.customData._serverResponse?.mfaPendingCredential,
authModular,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return MultiFactorResolverImpl._fromError(authModular, errorInternal);
}
function startEnrollTotpMfa(auth2, request) {
return _performApiRequest(auth2, "POST", "/v2/accounts/mfaEnrollment:start", _addTidIfNecessary(auth2, request));
}
function finalizeEnrollTotpMfa(auth2, request) {
return _performApiRequest(auth2, "POST", "/v2/accounts/mfaEnrollment:finalize", _addTidIfNecessary(auth2, request));
}
function withdrawMfa(auth2, request) {
return _performApiRequest(auth2, "POST", "/v2/accounts/mfaEnrollment:withdraw", _addTidIfNecessary(auth2, request));
}
function multiFactor(user) {
const userModular = getModularInstance(user);
if (!multiFactorUserCache.has(userModular)) {
multiFactorUserCache.set(userModular, MultiFactorUserImpl._fromUser(userModular));
}
return multiFactorUserCache.get(userModular);
}
function getVersionForPlatform(clientPlatform) {
switch (clientPlatform) {
case "Node":
return "node";
case "ReactNative":
return "rn";
case "Worker":
return "webworker";
case "Cordova":
return "cordova";
case "WebExtension":
return "web-extension";
default:
return void 0;
}
}
function registerAuth(clientPlatform) {
_registerComponent(new Component(
"auth",
(container, { options: deps }) => {
const app2 = container.getProvider("app").getImmediate();
const heartbeatServiceProvider = container.getProvider("heartbeat");
const appCheckServiceProvider = container.getProvider("app-check-internal");
const { apiKey, authDomain } = app2.options;
_assert(apiKey && !apiKey.includes(":"), "invalid-api-key", { appName: app2.name });
const config = {
apiKey,
authDomain,
clientPlatform,
apiHost: "identitytoolkit.googleapis.com",
tokenApiHost: "securetoken.googleapis.com",
apiScheme: "https",
sdkClientVersion: _getClientVersion(clientPlatform)
};
const authInstance = new AuthImpl(app2, heartbeatServiceProvider, appCheckServiceProvider, config);
_initializeAuthInstance(authInstance, deps);
return authInstance;
},
"PUBLIC"
/* ComponentType.PUBLIC */
).setInstantiationMode(
"EXPLICIT"
/* InstantiationMode.EXPLICIT */
).setInstanceCreatedCallback((container, _instanceIdentifier, _instance) => {
const authInternalProvider = container.getProvider(
"auth-internal"
/* _ComponentName.AUTH_INTERNAL */
);
authInternalProvider.initialize();
}));
_registerComponent(new Component(
"auth-internal",
(container) => {
const auth2 = _castAuth(container.getProvider(
"auth"
/* _ComponentName.AUTH */
).getImmediate());
return ((auth3) => new AuthInterop(auth3))(auth2);
},
"PRIVATE"
/* ComponentType.PRIVATE */
).setInstantiationMode(
"EXPLICIT"
/* InstantiationMode.EXPLICIT */
));
registerVersion(name3, version3, getVersionForPlatform(clientPlatform));
registerVersion(name3, version3, "esm2020");
}
function getAuth(app2 = getApp()) {
const provider = _getProvider(app2, "auth");
if (provider.isInitialized()) {
return provider.getImmediate();
}
const auth2 = initializeAuth(app2);
const authEmulatorHost = getDefaultEmulatorHost("auth");
if (authEmulatorHost) {
connectAuthEmulator(auth2, `http://${authEmulatorHost}`);
}
return auth2;
}
async function fail() {
throw NOT_AVAILABLE_ERROR;
}
function finalizeSignInTotpMfa(auth2, request) {
return _performApiRequest(auth2, "POST", "/v2/accounts/mfaSignIn:finalize", _addTidIfNecessary(auth2, request));
}
function _isEmptyString(input) {
return typeof input === "undefined" || input?.length === 0;
}
var FactorId, ProviderId, SignInMethod, OperationType, ActionCodeOperation, debugErrorMap, prodErrorMap, _DEFAULT_AUTH_ERROR_FACTORY, AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY, logClient, Delay, FetchProvider, SERVER_ERROR_MAP, CookieAuthProxiedEndpoints, DEFAULT_API_TIMEOUT_MS, NetworkTimeout, RecaptchaConfig, ProactiveRefresh, UserMetadata, StsTokenManager, UserImpl, instanceCache, InMemoryPersistence, inMemoryPersistence, PersistenceUserManager, AuthMiddlewareQueue, MINIMUM_MIN_PASSWORD_LENGTH, PasswordPolicyImpl, AuthImpl, Subscription, externalJSProvider, MockGreCAPTCHATopLevel, MockGreCAPTCHA, RECAPTCHA_ENTERPRISE_VERIFIER_TYPE, FAKE_TOKEN, RecaptchaEnterpriseVerifier, AuthCredential, EmailAuthCredential, IDP_REQUEST_URI$1, OAuthCredential, VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_, PhoneAuthCredential, ActionCodeURL, EmailAuthProvider, FederatedAuthProvider, BaseOAuthProvider, OAuthProvider, FacebookAuthProvider, GoogleAuthProvider, GithubAuthProvider, IDP_REQUEST_URI, SAMLAuthCredential, SAML_PROVIDER_PREFIX, SAMLAuthProvider, TwitterAuthProvider, UserCredentialImpl, MultiFactorError, MultiFactorInfoImpl, PhoneMultiFactorInfoImpl, TotpMultiFactorInfoImpl, GenericAdditionalUserInfo, FederatedAdditionalUserInfoWithUsername, FacebookAdditionalUserInfo, GithubAdditionalUserInfo, GoogleAdditionalUserInfo, TwitterAdditionalUserInfo, MultiFactorSessionImpl, MultiFactorResolverImpl, MultiFactorUserImpl, multiFactorUserCache, name3, version3, AuthInterop, NOT_AVAILABLE_ERROR, FailClass, browserLocalPersistence, browserSessionPersistence, browserCookiePersistence, indexedDBLocalPersistence, browserPopupRedirectResolver, PhoneAuthProvider, signInWithPhoneNumber, linkWithPhoneNumber, reauthenticateWithPhoneNumber, updatePhoneNumber, signInWithPopup, linkWithPopup, reauthenticateWithPopup, signInWithRedirect, linkWithRedirect, reauthenticateWithRedirect, getRedirectResult, RecaptchaVerifier, PhoneMultiFactorGenerator, MultiFactorAssertionImpl, TotpMultiFactorGenerator, TotpMultiFactorAssertionImpl, TotpSecret;
var init_totp_c8d207b9 = __esm({
"node_modules/@firebase/auth/dist/node-esm/totp-c8d207b9.js"() {
init_index_esm3();
init_index_node_esm();
init_index_esm();
init_index_esm2();
FactorId = {
/** Phone as second factor */
PHONE: "phone",
TOTP: "totp"
};
ProviderId = {
/** Facebook provider ID */
FACEBOOK: "facebook.com",
/** GitHub provider ID */
GITHUB: "github.com",
/** Google provider ID */
GOOGLE: "google.com",
/** Password provider */
PASSWORD: "password",
/** Phone provider */
PHONE: "phone",
/** Twitter provider ID */
TWITTER: "twitter.com"
};
SignInMethod = {
/** Email link sign in method */
EMAIL_LINK: "emailLink",
/** Email/password sign in method */
EMAIL_PASSWORD: "password",
/** Facebook sign in method */
FACEBOOK: "facebook.com",
/** GitHub sign in method */
GITHUB: "github.com",
/** Google sign in method */
GOOGLE: "google.com",
/** Phone sign in method */
PHONE: "phone",
/** Twitter sign in method */
TWITTER: "twitter.com"
};
OperationType = {
/** Operation involving linking an additional provider to an already signed-in user. */
LINK: "link",
/** Operation involving using a provider to reauthenticate an already signed-in user. */
REAUTHENTICATE: "reauthenticate",
/** Operation involving signing in a user. */
SIGN_IN: "signIn"
};
ActionCodeOperation = {
/** The email link sign-in action. */
EMAIL_SIGNIN: "EMAIL_SIGNIN",
/** The password reset action. */
PASSWORD_RESET: "PASSWORD_RESET",
/** The email revocation action. */
RECOVER_EMAIL: "RECOVER_EMAIL",
/** The revert second factor addition email action. */
REVERT_SECOND_FACTOR_ADDITION: "REVERT_SECOND_FACTOR_ADDITION",
/** The revert second factor addition email action. */
VERIFY_AND_CHANGE_EMAIL: "VERIFY_AND_CHANGE_EMAIL",
/** The email verification action. */
VERIFY_EMAIL: "VERIFY_EMAIL"
};
debugErrorMap = _debugErrorMap;
prodErrorMap = _prodErrorMap;
_DEFAULT_AUTH_ERROR_FACTORY = new ErrorFactory("auth", "Firebase", _prodErrorMap());
AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
ADMIN_ONLY_OPERATION: "auth/admin-restricted-operation",
ARGUMENT_ERROR: "auth/argument-error",
APP_NOT_AUTHORIZED: "auth/app-not-authorized",
APP_NOT_INSTALLED: "auth/app-not-installed",
CAPTCHA_CHECK_FAILED: "auth/captcha-check-failed",
CODE_EXPIRED: "auth/code-expired",
CORDOVA_NOT_READY: "auth/cordova-not-ready",
CORS_UNSUPPORTED: "auth/cors-unsupported",
CREDENTIAL_ALREADY_IN_USE: "auth/credential-already-in-use",
CREDENTIAL_MISMATCH: "auth/custom-token-mismatch",
CREDENTIAL_TOO_OLD_LOGIN_AGAIN: "auth/requires-recent-login",
DEPENDENT_SDK_INIT_BEFORE_AUTH: "auth/dependent-sdk-initialized-before-auth",
DYNAMIC_LINK_NOT_ACTIVATED: "auth/dynamic-link-not-activated",
EMAIL_CHANGE_NEEDS_VERIFICATION: "auth/email-change-needs-verification",
EMAIL_EXISTS: "auth/email-already-in-use",
EMULATOR_CONFIG_FAILED: "auth/emulator-config-failed",
EXPIRED_OOB_CODE: "auth/expired-action-code",
EXPIRED_POPUP_REQUEST: "auth/cancelled-popup-request",
INTERNAL_ERROR: "auth/internal-error",
INVALID_API_KEY: "auth/invalid-api-key",
INVALID_APP_CREDENTIAL: "auth/invalid-app-credential",
INVALID_APP_ID: "auth/invalid-app-id",
INVALID_AUTH: "auth/invalid-user-token",
INVALID_AUTH_EVENT: "auth/invalid-auth-event",
INVALID_CERT_HASH: "auth/invalid-cert-hash",
INVALID_CODE: "auth/invalid-verification-code",
INVALID_CONTINUE_URI: "auth/invalid-continue-uri",
INVALID_CORDOVA_CONFIGURATION: "auth/invalid-cordova-configuration",
INVALID_CUSTOM_TOKEN: "auth/invalid-custom-token",
INVALID_DYNAMIC_LINK_DOMAIN: "auth/invalid-dynamic-link-domain",
INVALID_EMAIL: "auth/invalid-email",
INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme",
INVALID_IDP_RESPONSE: "auth/invalid-credential",
INVALID_LOGIN_CREDENTIALS: "auth/invalid-credential",
INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload",
INVALID_MFA_SESSION: "auth/invalid-multi-factor-session",
INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id",
INVALID_OAUTH_PROVIDER: "auth/invalid-oauth-provider",
INVALID_OOB_CODE: "auth/invalid-action-code",
INVALID_ORIGIN: "auth/unauthorized-domain",
INVALID_PASSWORD: "auth/wrong-password",
INVALID_PERSISTENCE: "auth/invalid-persistence-type",
INVALID_PHONE_NUMBER: "auth/invalid-phone-number",
INVALID_PROVIDER_ID: "auth/invalid-provider-id",
INVALID_RECIPIENT_EMAIL: "auth/invalid-recipient-email",
INVALID_SENDER: "auth/invalid-sender",
INVALID_SESSION_INFO: "auth/invalid-verification-id",
INVALID_TENANT_ID: "auth/invalid-tenant-id",
MFA_INFO_NOT_FOUND: "auth/multi-factor-info-not-found",
MFA_REQUIRED: "auth/multi-factor-auth-required",
MISSING_ANDROID_PACKAGE_NAME: "auth/missing-android-pkg-name",
MISSING_APP_CREDENTIAL: "auth/missing-app-credential",
MISSING_AUTH_DOMAIN: "auth/auth-domain-config-required",
MISSING_CODE: "auth/missing-verification-code",
MISSING_CONTINUE_URI: "auth/missing-continue-uri",
MISSING_IFRAME_START: "auth/missing-iframe-start",
MISSING_IOS_BUNDLE_ID: "auth/missing-ios-bundle-id",
MISSING_OR_INVALID_NONCE: "auth/missing-or-invalid-nonce",
MISSING_MFA_INFO: "auth/missing-multi-factor-info",
MISSING_MFA_SESSION: "auth/missing-multi-factor-session",
MISSING_PHONE_NUMBER: "auth/missing-phone-number",
MISSING_PASSWORD: "auth/missing-password",
MISSING_SESSION_INFO: "auth/missing-verification-id",
MODULE_DESTROYED: "auth/app-deleted",
NEED_CONFIRMATION: "auth/account-exists-with-different-credential",
NETWORK_REQUEST_FAILED: "auth/network-request-failed",
NULL_USER: "auth/null-user",
NO_AUTH_EVENT: "auth/no-auth-event",
NO_SUCH_PROVIDER: "auth/no-such-provider",
OPERATION_NOT_ALLOWED: "auth/operation-not-allowed",
OPERATION_NOT_SUPPORTED: "auth/operation-not-supported-in-this-environment",
POPUP_BLOCKED: "auth/popup-blocked",
POPUP_CLOSED_BY_USER: "auth/popup-closed-by-user",
PROVIDER_ALREADY_LINKED: "auth/provider-already-linked",
QUOTA_EXCEEDED: "auth/quota-exceeded",
REDIRECT_CANCELLED_BY_USER: "auth/redirect-cancelled-by-user",
REDIRECT_OPERATION_PENDING: "auth/redirect-operation-pending",
REJECTED_CREDENTIAL: "auth/rejected-credential",
SECOND_FACTOR_ALREADY_ENROLLED: "auth/second-factor-already-in-use",
SECOND_FACTOR_LIMIT_EXCEEDED: "auth/maximum-second-factor-count-exceeded",
TENANT_ID_MISMATCH: "auth/tenant-id-mismatch",
TIMEOUT: "auth/timeout",
TOKEN_EXPIRED: "auth/user-token-expired",
TOO_MANY_ATTEMPTS_TRY_LATER: "auth/too-many-requests",
UNAUTHORIZED_DOMAIN: "auth/unauthorized-continue-uri",
UNSUPPORTED_FIRST_FACTOR: "auth/unsupported-first-factor",
UNSUPPORTED_PERSISTENCE: "auth/unsupported-persistence-type",
UNSUPPORTED_TENANT_OPERATION: "auth/unsupported-tenant-operation",
UNVERIFIED_EMAIL: "auth/unverified-email",
USER_CANCELLED: "auth/user-cancelled",
USER_DELETED: "auth/user-not-found",
USER_DISABLED: "auth/user-disabled",
USER_MISMATCH: "auth/user-mismatch",
USER_SIGNED_OUT: "auth/user-signed-out",
WEAK_PASSWORD: "auth/weak-password",
WEB_STORAGE_UNSUPPORTED: "auth/web-storage-unsupported",
ALREADY_INITIALIZED: "auth/already-initialized",
RECAPTCHA_NOT_ENABLED: "auth/recaptcha-not-enabled",
MISSING_RECAPTCHA_TOKEN: "auth/missing-recaptcha-token",
INVALID_RECAPTCHA_TOKEN: "auth/invalid-recaptcha-token",
INVALID_RECAPTCHA_ACTION: "auth/invalid-recaptcha-action",
MISSING_CLIENT_TYPE: "auth/missing-client-type",
MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version",
INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version",
INVALID_REQ_TYPE: "auth/invalid-req-type",
INVALID_HOSTING_LINK_DOMAIN: "auth/invalid-hosting-link-domain"
};
logClient = new Logger("@firebase/auth");
Delay = class {
constructor(shortDelay, longDelay) {
this.shortDelay = shortDelay;
this.longDelay = longDelay;
debugAssert(longDelay > shortDelay, "Short delay should be less than long delay!");
this.isMobile = isMobileCordova() || isReactNative();
}
get() {
if (!_isOnline()) {
return Math.min(5e3, this.shortDelay);
}
return this.isMobile ? this.longDelay : this.shortDelay;
}
};
FetchProvider = class {
static initialize(fetchImpl, headersImpl, responseImpl) {
this.fetchImpl = fetchImpl;
if (headersImpl) {
this.headersImpl = headersImpl;
}
if (responseImpl) {
this.responseImpl = responseImpl;
}
}
static fetch() {
if (this.fetchImpl) {
return this.fetchImpl;
}
if (typeof self !== "undefined" && "fetch" in self) {
return self.fetch;
}
if (typeof globalThis !== "undefined" && globalThis.fetch) {
return globalThis.fetch;
}
if (typeof fetch !== "undefined") {
return fetch;
}
debugFail("Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill");
}
static headers() {
if (this.headersImpl) {
return this.headersImpl;
}
if (typeof self !== "undefined" && "Headers" in self) {
return self.Headers;
}
if (typeof globalThis !== "undefined" && globalThis.Headers) {
return globalThis.Headers;
}
if (typeof Headers !== "undefined") {
return Headers;
}
debugFail("Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill");
}
static response() {
if (this.responseImpl) {
return this.responseImpl;
}
if (typeof self !== "undefined" && "Response" in self) {
return self.Response;
}
if (typeof globalThis !== "undefined" && globalThis.Response) {
return globalThis.Response;
}
if (typeof Response !== "undefined") {
return Response;
}
debugFail("Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill");
}
};
SERVER_ERROR_MAP = {
// Custom token errors.
[
"CREDENTIAL_MISMATCH"
/* ServerError.CREDENTIAL_MISMATCH */
]: "custom-token-mismatch",
// This can only happen if the SDK sends a bad request.
[
"MISSING_CUSTOM_TOKEN"
/* ServerError.MISSING_CUSTOM_TOKEN */
]: "internal-error",
// Create Auth URI errors.
[
"INVALID_IDENTIFIER"
/* ServerError.INVALID_IDENTIFIER */
]: "invalid-email",
// This can only happen if the SDK sends a bad request.
[
"MISSING_CONTINUE_URI"
/* ServerError.MISSING_CONTINUE_URI */
]: "internal-error",
// Sign in with email and password errors (some apply to sign up too).
[
"INVALID_PASSWORD"
/* ServerError.INVALID_PASSWORD */
]: "wrong-password",
// This can only happen if the SDK sends a bad request.
[
"MISSING_PASSWORD"
/* ServerError.MISSING_PASSWORD */
]: "missing-password",
// Thrown if Email Enumeration Protection is enabled in the project and the email or password is
// invalid.
[
"INVALID_LOGIN_CREDENTIALS"
/* ServerError.INVALID_LOGIN_CREDENTIALS */
]: "invalid-credential",
// Sign up with email and password errors.
[
"EMAIL_EXISTS"
/* ServerError.EMAIL_EXISTS */
]: "email-already-in-use",
[
"PASSWORD_LOGIN_DISABLED"
/* ServerError.PASSWORD_LOGIN_DISABLED */
]: "operation-not-allowed",
// Verify assertion for sign in with credential errors:
[
"INVALID_IDP_RESPONSE"
/* ServerError.INVALID_IDP_RESPONSE */
]: "invalid-credential",
[
"INVALID_PENDING_TOKEN"
/* ServerError.INVALID_PENDING_TOKEN */
]: "invalid-credential",
[
"FEDERATED_USER_ID_ALREADY_LINKED"
/* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */
]: "credential-already-in-use",
// This can only happen if the SDK sends a bad request.
[
"MISSING_REQ_TYPE"
/* ServerError.MISSING_REQ_TYPE */
]: "internal-error",
// Send Password reset email errors:
[
"EMAIL_NOT_FOUND"
/* ServerError.EMAIL_NOT_FOUND */
]: "user-not-found",
[
"RESET_PASSWORD_EXCEED_LIMIT"
/* ServerError.RESET_PASSWORD_EXCEED_LIMIT */
]: "too-many-requests",
[
"EXPIRED_OOB_CODE"
/* ServerError.EXPIRED_OOB_CODE */
]: "expired-action-code",
[
"INVALID_OOB_CODE"
/* ServerError.INVALID_OOB_CODE */
]: "invalid-action-code",
// This can only happen if the SDK sends a bad request.
[
"MISSING_OOB_CODE"
/* ServerError.MISSING_OOB_CODE */
]: "internal-error",
// Operations that require ID token in request:
[
"CREDENTIAL_TOO_OLD_LOGIN_AGAIN"
/* ServerError.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
]: "requires-recent-login",
[
"INVALID_ID_TOKEN"
/* ServerError.INVALID_ID_TOKEN */
]: "invalid-user-token",
[
"TOKEN_EXPIRED"
/* ServerError.TOKEN_EXPIRED */
]: "user-token-expired",
[
"USER_NOT_FOUND"
/* ServerError.USER_NOT_FOUND */
]: "user-token-expired",
// Other errors.
[
"TOO_MANY_ATTEMPTS_TRY_LATER"
/* ServerError.TOO_MANY_ATTEMPTS_TRY_LATER */
]: "too-many-requests",
[
"PASSWORD_DOES_NOT_MEET_REQUIREMENTS"
/* ServerError.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */
]: "password-does-not-meet-requirements",
// Phone Auth related errors.
[
"INVALID_CODE"
/* ServerError.INVALID_CODE */
]: "invalid-verification-code",
[
"INVALID_SESSION_INFO"
/* ServerError.INVALID_SESSION_INFO */
]: "invalid-verification-id",
[
"INVALID_TEMPORARY_PROOF"
/* ServerError.INVALID_TEMPORARY_PROOF */
]: "invalid-credential",
[
"MISSING_SESSION_INFO"
/* ServerError.MISSING_SESSION_INFO */
]: "missing-verification-id",
[
"SESSION_EXPIRED"
/* ServerError.SESSION_EXPIRED */
]: "code-expired",
// Other action code errors when additional settings passed.
// MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above.
// This is OK as this error will be caught by client side validation.
[
"MISSING_ANDROID_PACKAGE_NAME"
/* ServerError.MISSING_ANDROID_PACKAGE_NAME */
]: "missing-android-pkg-name",
[
"UNAUTHORIZED_DOMAIN"
/* ServerError.UNAUTHORIZED_DOMAIN */
]: "unauthorized-continue-uri",
// getProjectConfig errors when clientId is passed.
[
"INVALID_OAUTH_CLIENT_ID"
/* ServerError.INVALID_OAUTH_CLIENT_ID */
]: "invalid-oauth-client-id",
// User actions (sign-up or deletion) disabled errors.
[
"ADMIN_ONLY_OPERATION"
/* ServerError.ADMIN_ONLY_OPERATION */
]: "admin-restricted-operation",
// Multi factor related errors.
[
"INVALID_MFA_PENDING_CREDENTIAL"
/* ServerError.INVALID_MFA_PENDING_CREDENTIAL */
]: "invalid-multi-factor-session",
[
"MFA_ENROLLMENT_NOT_FOUND"
/* ServerError.MFA_ENROLLMENT_NOT_FOUND */
]: "multi-factor-info-not-found",
[
"MISSING_MFA_ENROLLMENT_ID"
/* ServerError.MISSING_MFA_ENROLLMENT_ID */
]: "missing-multi-factor-info",
[
"MISSING_MFA_PENDING_CREDENTIAL"
/* ServerError.MISSING_MFA_PENDING_CREDENTIAL */
]: "missing-multi-factor-session",
[
"SECOND_FACTOR_EXISTS"
/* ServerError.SECOND_FACTOR_EXISTS */
]: "second-factor-already-in-use",
[
"SECOND_FACTOR_LIMIT_EXCEEDED"
/* ServerError.SECOND_FACTOR_LIMIT_EXCEEDED */
]: "maximum-second-factor-count-exceeded",
// Blocking functions related errors.
[
"BLOCKING_FUNCTION_ERROR_RESPONSE"
/* ServerError.BLOCKING_FUNCTION_ERROR_RESPONSE */
]: "internal-error",
// Recaptcha related errors.
[
"RECAPTCHA_NOT_ENABLED"
/* ServerError.RECAPTCHA_NOT_ENABLED */
]: "recaptcha-not-enabled",
[
"MISSING_RECAPTCHA_TOKEN"
/* ServerError.MISSING_RECAPTCHA_TOKEN */
]: "missing-recaptcha-token",
[
"INVALID_RECAPTCHA_TOKEN"
/* ServerError.INVALID_RECAPTCHA_TOKEN */
]: "invalid-recaptcha-token",
[
"INVALID_RECAPTCHA_ACTION"
/* ServerError.INVALID_RECAPTCHA_ACTION */
]: "invalid-recaptcha-action",
[
"MISSING_CLIENT_TYPE"
/* ServerError.MISSING_CLIENT_TYPE */
]: "missing-client-type",
[
"MISSING_RECAPTCHA_VERSION"
/* ServerError.MISSING_RECAPTCHA_VERSION */
]: "missing-recaptcha-version",
[
"INVALID_RECAPTCHA_VERSION"
/* ServerError.INVALID_RECAPTCHA_VERSION */
]: "invalid-recaptcha-version",
[
"INVALID_REQ_TYPE"
/* ServerError.INVALID_REQ_TYPE */
]: "invalid-req-type"
/* AuthErrorCode.INVALID_REQ_TYPE */
};
CookieAuthProxiedEndpoints = [
"/v1/accounts:signInWithCustomToken",
"/v1/accounts:signInWithEmailLink",
"/v1/accounts:signInWithIdp",
"/v1/accounts:signInWithPassword",
"/v1/accounts:signInWithPhoneNumber",
"/v1/token"
/* Endpoint.TOKEN */
];
DEFAULT_API_TIMEOUT_MS = new Delay(3e4, 6e4);
NetworkTimeout = class {
clearNetworkTimeout() {
clearTimeout(this.timer);
}
constructor(auth2) {
this.auth = auth2;
this.timer = null;
this.promise = new Promise((_, reject) => {
this.timer = setTimeout(() => {
return reject(_createError(
this.auth,
"network-request-failed"
/* AuthErrorCode.NETWORK_REQUEST_FAILED */
));
}, DEFAULT_API_TIMEOUT_MS.get());
});
}
};
RecaptchaConfig = class {
constructor(response) {
this.siteKey = "";
this.recaptchaEnforcementState = [];
if (response.recaptchaKey === void 0) {
throw new Error("recaptchaKey undefined");
}
this.siteKey = response.recaptchaKey.split("/")[3];
this.recaptchaEnforcementState = response.recaptchaEnforcementState;
}
/**
* Returns the reCAPTCHA Enterprise enforcement state for the given provider.
*
* @param providerStr - The provider whose enforcement state is to be returned.
* @returns The reCAPTCHA Enterprise enforcement state for the given provider.
*/
getProviderEnforcementState(providerStr) {
if (!this.recaptchaEnforcementState || this.recaptchaEnforcementState.length === 0) {
return null;
}
for (const recaptchaEnforcementState of this.recaptchaEnforcementState) {
if (recaptchaEnforcementState.provider && recaptchaEnforcementState.provider === providerStr) {
return _parseEnforcementState(recaptchaEnforcementState.enforcementState);
}
}
return null;
}
/**
* Returns true if the reCAPTCHA Enterprise enforcement state for the provider is set to ENFORCE or AUDIT.
*
* @param providerStr - The provider whose enablement state is to be returned.
* @returns Whether or not reCAPTCHA Enterprise protection is enabled for the given provider.
*/
isProviderEnabled(providerStr) {
return this.getProviderEnforcementState(providerStr) === "ENFORCE" || this.getProviderEnforcementState(providerStr) === "AUDIT";
}
/**
* Returns true if reCAPTCHA Enterprise protection is enabled in at least one provider, otherwise
* returns false.
*
* @returns Whether or not reCAPTCHA Enterprise protection is enabled for at least one provider.
*/
isAnyProviderEnabled() {
return this.isProviderEnabled(
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
) || this.isProviderEnabled(
"PHONE_PROVIDER"
/* RecaptchaAuthProvider.PHONE_PROVIDER */
);
}
};
ProactiveRefresh = class {
constructor(user) {
this.user = user;
this.isRunning = false;
this.timerId = null;
this.errorBackoff = 3e4;
}
_start() {
if (this.isRunning) {
return;
}
this.isRunning = true;
this.schedule();
}
_stop() {
if (!this.isRunning) {
return;
}
this.isRunning = false;
if (this.timerId !== null) {
clearTimeout(this.timerId);
}
}
getInterval(wasError) {
if (wasError) {
const interval = this.errorBackoff;
this.errorBackoff = Math.min(
this.errorBackoff * 2,
96e4
/* Duration.RETRY_BACKOFF_MAX */
);
return interval;
} else {
this.errorBackoff = 3e4;
const expTime = this.user.stsTokenManager.expirationTime ?? 0;
const interval = expTime - Date.now() - 3e5;
return Math.max(0, interval);
}
}
schedule(wasError = false) {
if (!this.isRunning) {
return;
}
const interval = this.getInterval(wasError);
this.timerId = setTimeout(async () => {
await this.iteration();
}, interval);
}
async iteration() {
try {
await this.user.getIdToken(true);
} catch (e) {
if (e?.code === `auth/${"network-request-failed"}`) {
this.schedule(
/* wasError */
true
);
}
return;
}
this.schedule();
}
};
UserMetadata = class {
constructor(createdAt, lastLoginAt) {
this.createdAt = createdAt;
this.lastLoginAt = lastLoginAt;
this._initializeTime();
}
_initializeTime() {
this.lastSignInTime = utcTimestampToDateString(this.lastLoginAt);
this.creationTime = utcTimestampToDateString(this.createdAt);
}
_copy(metadata) {
this.createdAt = metadata.createdAt;
this.lastLoginAt = metadata.lastLoginAt;
this._initializeTime();
}
toJSON() {
return {
createdAt: this.createdAt,
lastLoginAt: this.lastLoginAt
};
}
};
StsTokenManager = class _StsTokenManager {
constructor() {
this.refreshToken = null;
this.accessToken = null;
this.expirationTime = null;
}
get isExpired() {
return !this.expirationTime || Date.now() > this.expirationTime - 3e4;
}
updateFromServerResponse(response) {
_assert(
response.idToken,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert(
typeof response.idToken !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert(
typeof response.refreshToken !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const expiresIn = "expiresIn" in response && typeof response.expiresIn !== "undefined" ? Number(response.expiresIn) : _tokenExpiresIn(response.idToken);
this.updateTokensAndExpiration(response.idToken, response.refreshToken, expiresIn);
}
updateFromIdToken(idToken) {
_assert(
idToken.length !== 0,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const expiresIn = _tokenExpiresIn(idToken);
this.updateTokensAndExpiration(idToken, null, expiresIn);
}
async getToken(auth2, forceRefresh = false) {
if (!forceRefresh && this.accessToken && !this.isExpired) {
return this.accessToken;
}
_assert(
this.refreshToken,
auth2,
"user-token-expired"
/* AuthErrorCode.TOKEN_EXPIRED */
);
if (this.refreshToken) {
await this.refresh(auth2, this.refreshToken);
return this.accessToken;
}
return null;
}
clearRefreshToken() {
this.refreshToken = null;
}
async refresh(auth2, oldToken) {
const { accessToken, refreshToken, expiresIn } = await requestStsToken(auth2, oldToken);
this.updateTokensAndExpiration(accessToken, refreshToken, Number(expiresIn));
}
updateTokensAndExpiration(accessToken, refreshToken, expiresInSec) {
this.refreshToken = refreshToken || null;
this.accessToken = accessToken || null;
this.expirationTime = Date.now() + expiresInSec * 1e3;
}
static fromJSON(appName, object) {
const { refreshToken, accessToken, expirationTime } = object;
const manager = new _StsTokenManager();
if (refreshToken) {
_assert(typeof refreshToken === "string", "internal-error", {
appName
});
manager.refreshToken = refreshToken;
}
if (accessToken) {
_assert(typeof accessToken === "string", "internal-error", {
appName
});
manager.accessToken = accessToken;
}
if (expirationTime) {
_assert(typeof expirationTime === "number", "internal-error", {
appName
});
manager.expirationTime = expirationTime;
}
return manager;
}
toJSON() {
return {
refreshToken: this.refreshToken,
accessToken: this.accessToken,
expirationTime: this.expirationTime
};
}
_assign(stsTokenManager) {
this.accessToken = stsTokenManager.accessToken;
this.refreshToken = stsTokenManager.refreshToken;
this.expirationTime = stsTokenManager.expirationTime;
}
_clone() {
return Object.assign(new _StsTokenManager(), this.toJSON());
}
_performRefresh() {
return debugFail("not implemented");
}
};
UserImpl = class _UserImpl {
constructor({ uid, auth: auth2, stsTokenManager, ...opt }) {
this.providerId = "firebase";
this.proactiveRefresh = new ProactiveRefresh(this);
this.reloadUserInfo = null;
this.reloadListener = null;
this.uid = uid;
this.auth = auth2;
this.stsTokenManager = stsTokenManager;
this.accessToken = stsTokenManager.accessToken;
this.displayName = opt.displayName || null;
this.email = opt.email || null;
this.emailVerified = opt.emailVerified || false;
this.phoneNumber = opt.phoneNumber || null;
this.photoURL = opt.photoURL || null;
this.isAnonymous = opt.isAnonymous || false;
this.tenantId = opt.tenantId || null;
this.providerData = opt.providerData ? [...opt.providerData] : [];
this.metadata = new UserMetadata(opt.createdAt || void 0, opt.lastLoginAt || void 0);
}
async getIdToken(forceRefresh) {
const accessToken = await _logoutIfInvalidated(this, this.stsTokenManager.getToken(this.auth, forceRefresh));
_assert(
accessToken,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
if (this.accessToken !== accessToken) {
this.accessToken = accessToken;
await this.auth._persistUserIfCurrent(this);
this.auth._notifyListenersIfCurrent(this);
}
return accessToken;
}
getIdTokenResult(forceRefresh) {
return getIdTokenResult(this, forceRefresh);
}
reload() {
return reload(this);
}
_assign(user) {
if (this === user) {
return;
}
_assert(
this.uid === user.uid,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
this.displayName = user.displayName;
this.photoURL = user.photoURL;
this.email = user.email;
this.emailVerified = user.emailVerified;
this.phoneNumber = user.phoneNumber;
this.isAnonymous = user.isAnonymous;
this.tenantId = user.tenantId;
this.providerData = user.providerData.map((userInfo) => ({ ...userInfo }));
this.metadata._copy(user.metadata);
this.stsTokenManager._assign(user.stsTokenManager);
}
_clone(auth2) {
const newUser = new _UserImpl({
...this,
auth: auth2,
stsTokenManager: this.stsTokenManager._clone()
});
newUser.metadata._copy(this.metadata);
return newUser;
}
_onReload(callback) {
_assert(
!this.reloadListener,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
this.reloadListener = callback;
if (this.reloadUserInfo) {
this._notifyReloadListener(this.reloadUserInfo);
this.reloadUserInfo = null;
}
}
_notifyReloadListener(userInfo) {
if (this.reloadListener) {
this.reloadListener(userInfo);
} else {
this.reloadUserInfo = userInfo;
}
}
_startProactiveRefresh() {
this.proactiveRefresh._start();
}
_stopProactiveRefresh() {
this.proactiveRefresh._stop();
}
async _updateTokensIfNecessary(response, reload2 = false) {
let tokensRefreshed = false;
if (response.idToken && response.idToken !== this.stsTokenManager.accessToken) {
this.stsTokenManager.updateFromServerResponse(response);
tokensRefreshed = true;
}
if (reload2) {
await _reloadWithoutSaving(this);
}
await this.auth._persistUserIfCurrent(this);
if (tokensRefreshed) {
this.auth._notifyListenersIfCurrent(this);
}
}
async delete() {
if (_isFirebaseServerApp(this.auth.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this.auth));
}
const idToken = await this.getIdToken();
await _logoutIfInvalidated(this, deleteAccount(this.auth, { idToken }));
this.stsTokenManager.clearRefreshToken();
return this.auth.signOut();
}
toJSON() {
return {
uid: this.uid,
email: this.email || void 0,
emailVerified: this.emailVerified,
displayName: this.displayName || void 0,
isAnonymous: this.isAnonymous,
photoURL: this.photoURL || void 0,
phoneNumber: this.phoneNumber || void 0,
tenantId: this.tenantId || void 0,
providerData: this.providerData.map((userInfo) => ({ ...userInfo })),
stsTokenManager: this.stsTokenManager.toJSON(),
// Redirect event ID must be maintained in case there is a pending
// redirect event.
_redirectEventId: this._redirectEventId,
...this.metadata.toJSON(),
// Required for compatibility with the legacy SDK (go/firebase-auth-sdk-persistence-parsing):
apiKey: this.auth.config.apiKey,
appName: this.auth.name
// Missing authDomain will be tolerated by the legacy SDK.
// stsTokenManager.apiKey isn't actually required (despite the legacy SDK persisting it).
};
}
get refreshToken() {
return this.stsTokenManager.refreshToken || "";
}
static _fromJSON(auth2, object) {
const displayName = object.displayName ?? void 0;
const email = object.email ?? void 0;
const phoneNumber = object.phoneNumber ?? void 0;
const photoURL = object.photoURL ?? void 0;
const tenantId = object.tenantId ?? void 0;
const _redirectEventId = object._redirectEventId ?? void 0;
const createdAt = object.createdAt ?? void 0;
const lastLoginAt = object.lastLoginAt ?? void 0;
const { uid, emailVerified, isAnonymous, providerData, stsTokenManager: plainObjectTokenManager } = object;
_assert(
uid && plainObjectTokenManager,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const stsTokenManager = StsTokenManager.fromJSON(this.name, plainObjectTokenManager);
_assert(
typeof uid === "string",
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
assertStringOrUndefined(displayName, auth2.name);
assertStringOrUndefined(email, auth2.name);
_assert(
typeof emailVerified === "boolean",
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert(
typeof isAnonymous === "boolean",
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
assertStringOrUndefined(phoneNumber, auth2.name);
assertStringOrUndefined(photoURL, auth2.name);
assertStringOrUndefined(tenantId, auth2.name);
assertStringOrUndefined(_redirectEventId, auth2.name);
assertStringOrUndefined(createdAt, auth2.name);
assertStringOrUndefined(lastLoginAt, auth2.name);
const user = new _UserImpl({
uid,
auth: auth2,
email,
emailVerified,
displayName,
isAnonymous,
photoURL,
phoneNumber,
tenantId,
stsTokenManager,
createdAt,
lastLoginAt
});
if (providerData && Array.isArray(providerData)) {
user.providerData = providerData.map((userInfo) => ({ ...userInfo }));
}
if (_redirectEventId) {
user._redirectEventId = _redirectEventId;
}
return user;
}
/**
* Initialize a User from an idToken server response
* @param auth
* @param idTokenResponse
*/
static async _fromIdTokenResponse(auth2, idTokenResponse, isAnonymous = false) {
const stsTokenManager = new StsTokenManager();
stsTokenManager.updateFromServerResponse(idTokenResponse);
const user = new _UserImpl({
uid: idTokenResponse.localId,
auth: auth2,
stsTokenManager,
isAnonymous
});
await _reloadWithoutSaving(user);
return user;
}
/**
* Initialize a User from an idToken server response
* @param auth
* @param idTokenResponse
*/
static async _fromGetAccountInfoResponse(auth2, response, idToken) {
const coreAccount = response.users[0];
_assert(
coreAccount.localId !== void 0,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const providerData = coreAccount.providerUserInfo !== void 0 ? extractProviderData(coreAccount.providerUserInfo) : [];
const isAnonymous = !(coreAccount.email && coreAccount.passwordHash) && !providerData?.length;
const stsTokenManager = new StsTokenManager();
stsTokenManager.updateFromIdToken(idToken);
const user = new _UserImpl({
uid: coreAccount.localId,
auth: auth2,
stsTokenManager,
isAnonymous
});
const updates = {
uid: coreAccount.localId,
displayName: coreAccount.displayName || null,
photoURL: coreAccount.photoUrl || null,
email: coreAccount.email || null,
emailVerified: coreAccount.emailVerified || false,
phoneNumber: coreAccount.phoneNumber || null,
tenantId: coreAccount.tenantId || null,
providerData,
metadata: new UserMetadata(coreAccount.createdAt, coreAccount.lastLoginAt),
isAnonymous: !(coreAccount.email && coreAccount.passwordHash) && !providerData?.length
};
Object.assign(user, updates);
return user;
}
};
instanceCache = /* @__PURE__ */ new Map();
InMemoryPersistence = class {
constructor() {
this.type = "NONE";
this.storage = {};
}
async _isAvailable() {
return true;
}
async _set(key, value) {
this.storage[key] = value;
}
async _get(key) {
const value = this.storage[key];
return value === void 0 ? null : value;
}
async _remove(key) {
delete this.storage[key];
}
_addListener(_key, _listener) {
return;
}
_removeListener(_key, _listener) {
return;
}
};
InMemoryPersistence.type = "NONE";
inMemoryPersistence = InMemoryPersistence;
PersistenceUserManager = class _PersistenceUserManager {
constructor(persistence, auth2, userKey) {
this.persistence = persistence;
this.auth = auth2;
this.userKey = userKey;
const { config, name: name6 } = this.auth;
this.fullUserKey = _persistenceKeyName(this.userKey, config.apiKey, name6);
this.fullPersistenceKey = _persistenceKeyName("persistence", config.apiKey, name6);
this.boundEventHandler = auth2._onStorageEvent.bind(auth2);
this.persistence._addListener(this.fullUserKey, this.boundEventHandler);
}
setCurrentUser(user) {
return this.persistence._set(this.fullUserKey, user.toJSON());
}
async getCurrentUser() {
const blob = await this.persistence._get(this.fullUserKey);
if (!blob) {
return null;
}
if (typeof blob === "string") {
const response = await getAccountInfo(this.auth, { idToken: blob }).catch(() => void 0);
if (!response) {
return null;
}
return UserImpl._fromGetAccountInfoResponse(this.auth, response, blob);
}
return UserImpl._fromJSON(this.auth, blob);
}
removeCurrentUser() {
return this.persistence._remove(this.fullUserKey);
}
savePersistenceForRedirect() {
return this.persistence._set(this.fullPersistenceKey, this.persistence.type);
}
async setPersistence(newPersistence) {
if (this.persistence === newPersistence) {
return;
}
const currentUser = await this.getCurrentUser();
await this.removeCurrentUser();
this.persistence = newPersistence;
if (currentUser) {
return this.setCurrentUser(currentUser);
}
}
delete() {
this.persistence._removeListener(this.fullUserKey, this.boundEventHandler);
}
static async create(auth2, persistenceHierarchy, userKey = "authUser") {
if (!persistenceHierarchy.length) {
return new _PersistenceUserManager(_getInstance(inMemoryPersistence), auth2, userKey);
}
const availablePersistences = (await Promise.all(persistenceHierarchy.map(async (persistence) => {
if (await persistence._isAvailable()) {
return persistence;
}
return void 0;
}))).filter((persistence) => persistence);
let selectedPersistence = availablePersistences[0] || _getInstance(inMemoryPersistence);
const key = _persistenceKeyName(userKey, auth2.config.apiKey, auth2.name);
let userToMigrate = null;
for (const persistence of persistenceHierarchy) {
try {
const blob = await persistence._get(key);
if (blob) {
let user;
if (typeof blob === "string") {
const response = await getAccountInfo(auth2, {
idToken: blob
}).catch(() => void 0);
if (!response) {
break;
}
user = await UserImpl._fromGetAccountInfoResponse(auth2, response, blob);
} else {
user = UserImpl._fromJSON(auth2, blob);
}
if (persistence !== selectedPersistence) {
userToMigrate = user;
}
selectedPersistence = persistence;
break;
}
} catch {
}
}
const migrationHierarchy = availablePersistences.filter((p) => p._shouldAllowMigration);
if (!selectedPersistence._shouldAllowMigration || !migrationHierarchy.length) {
return new _PersistenceUserManager(selectedPersistence, auth2, userKey);
}
selectedPersistence = migrationHierarchy[0];
if (userToMigrate) {
await selectedPersistence._set(key, userToMigrate.toJSON());
}
await Promise.all(persistenceHierarchy.map(async (persistence) => {
if (persistence !== selectedPersistence) {
try {
await persistence._remove(key);
} catch {
}
}
}));
return new _PersistenceUserManager(selectedPersistence, auth2, userKey);
}
};
AuthMiddlewareQueue = class {
constructor(auth2) {
this.auth = auth2;
this.queue = [];
}
pushCallback(callback, onAbort) {
const wrappedCallback = (user) => new Promise((resolve, reject) => {
try {
const result = callback(user);
resolve(result);
} catch (e) {
reject(e);
}
});
wrappedCallback.onAbort = onAbort;
this.queue.push(wrappedCallback);
const index = this.queue.length - 1;
return () => {
this.queue[index] = () => Promise.resolve();
};
}
async runMiddleware(nextUser) {
if (this.auth.currentUser === nextUser) {
return;
}
const onAbortStack = [];
try {
for (const beforeStateCallback of this.queue) {
await beforeStateCallback(nextUser);
if (beforeStateCallback.onAbort) {
onAbortStack.push(beforeStateCallback.onAbort);
}
}
} catch (e) {
onAbortStack.reverse();
for (const onAbort of onAbortStack) {
try {
onAbort();
} catch (_) {
}
}
throw this.auth._errorFactory.create("login-blocked", {
originalMessage: e?.message
});
}
}
};
MINIMUM_MIN_PASSWORD_LENGTH = 6;
PasswordPolicyImpl = class {
constructor(response) {
const responseOptions = response.customStrengthOptions;
this.customStrengthOptions = {};
this.customStrengthOptions.minPasswordLength = responseOptions.minPasswordLength ?? MINIMUM_MIN_PASSWORD_LENGTH;
if (responseOptions.maxPasswordLength) {
this.customStrengthOptions.maxPasswordLength = responseOptions.maxPasswordLength;
}
if (responseOptions.containsLowercaseCharacter !== void 0) {
this.customStrengthOptions.containsLowercaseLetter = responseOptions.containsLowercaseCharacter;
}
if (responseOptions.containsUppercaseCharacter !== void 0) {
this.customStrengthOptions.containsUppercaseLetter = responseOptions.containsUppercaseCharacter;
}
if (responseOptions.containsNumericCharacter !== void 0) {
this.customStrengthOptions.containsNumericCharacter = responseOptions.containsNumericCharacter;
}
if (responseOptions.containsNonAlphanumericCharacter !== void 0) {
this.customStrengthOptions.containsNonAlphanumericCharacter = responseOptions.containsNonAlphanumericCharacter;
}
this.enforcementState = response.enforcementState;
if (this.enforcementState === "ENFORCEMENT_STATE_UNSPECIFIED") {
this.enforcementState = "OFF";
}
this.allowedNonAlphanumericCharacters = response.allowedNonAlphanumericCharacters?.join("") ?? "";
this.forceUpgradeOnSignin = response.forceUpgradeOnSignin ?? false;
this.schemaVersion = response.schemaVersion;
}
validatePassword(password) {
const status = {
isValid: true,
passwordPolicy: this
};
this.validatePasswordLengthOptions(password, status);
this.validatePasswordCharacterOptions(password, status);
status.isValid && (status.isValid = status.meetsMinPasswordLength ?? true);
status.isValid && (status.isValid = status.meetsMaxPasswordLength ?? true);
status.isValid && (status.isValid = status.containsLowercaseLetter ?? true);
status.isValid && (status.isValid = status.containsUppercaseLetter ?? true);
status.isValid && (status.isValid = status.containsNumericCharacter ?? true);
status.isValid && (status.isValid = status.containsNonAlphanumericCharacter ?? true);
return status;
}
/**
* Validates that the password meets the length options for the policy.
*
* @param password Password to validate.
* @param status Validation status.
*/
validatePasswordLengthOptions(password, status) {
const minPasswordLength = this.customStrengthOptions.minPasswordLength;
const maxPasswordLength = this.customStrengthOptions.maxPasswordLength;
if (minPasswordLength) {
status.meetsMinPasswordLength = password.length >= minPasswordLength;
}
if (maxPasswordLength) {
status.meetsMaxPasswordLength = password.length <= maxPasswordLength;
}
}
/**
* Validates that the password meets the character options for the policy.
*
* @param password Password to validate.
* @param status Validation status.
*/
validatePasswordCharacterOptions(password, status) {
this.updatePasswordCharacterOptionsStatuses(
status,
/* containsLowercaseCharacter= */
false,
/* containsUppercaseCharacter= */
false,
/* containsNumericCharacter= */
false,
/* containsNonAlphanumericCharacter= */
false
);
let passwordChar;
for (let i = 0; i < password.length; i++) {
passwordChar = password.charAt(i);
this.updatePasswordCharacterOptionsStatuses(
status,
/* containsLowercaseCharacter= */
passwordChar >= "a" && passwordChar <= "z",
/* containsUppercaseCharacter= */
passwordChar >= "A" && passwordChar <= "Z",
/* containsNumericCharacter= */
passwordChar >= "0" && passwordChar <= "9",
/* containsNonAlphanumericCharacter= */
this.allowedNonAlphanumericCharacters.includes(passwordChar)
);
}
}
/**
* Updates the running validation status with the statuses for the character options.
* Expected to be called each time a character is processed to update each option status
* based on the current character.
*
* @param status Validation status.
* @param containsLowercaseCharacter Whether the character is a lowercase letter.
* @param containsUppercaseCharacter Whether the character is an uppercase letter.
* @param containsNumericCharacter Whether the character is a numeric character.
* @param containsNonAlphanumericCharacter Whether the character is a non-alphanumeric character.
*/
updatePasswordCharacterOptionsStatuses(status, containsLowercaseCharacter, containsUppercaseCharacter, containsNumericCharacter, containsNonAlphanumericCharacter) {
if (this.customStrengthOptions.containsLowercaseLetter) {
status.containsLowercaseLetter || (status.containsLowercaseLetter = containsLowercaseCharacter);
}
if (this.customStrengthOptions.containsUppercaseLetter) {
status.containsUppercaseLetter || (status.containsUppercaseLetter = containsUppercaseCharacter);
}
if (this.customStrengthOptions.containsNumericCharacter) {
status.containsNumericCharacter || (status.containsNumericCharacter = containsNumericCharacter);
}
if (this.customStrengthOptions.containsNonAlphanumericCharacter) {
status.containsNonAlphanumericCharacter || (status.containsNonAlphanumericCharacter = containsNonAlphanumericCharacter);
}
}
};
AuthImpl = class {
constructor(app2, heartbeatServiceProvider, appCheckServiceProvider, config) {
this.app = app2;
this.heartbeatServiceProvider = heartbeatServiceProvider;
this.appCheckServiceProvider = appCheckServiceProvider;
this.config = config;
this.currentUser = null;
this.emulatorConfig = null;
this.operations = Promise.resolve();
this.authStateSubscription = new Subscription(this);
this.idTokenSubscription = new Subscription(this);
this.beforeStateQueue = new AuthMiddlewareQueue(this);
this.redirectUser = null;
this.isProactiveRefreshEnabled = false;
this.EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION = 1;
this._canInitEmulator = true;
this._isInitialized = false;
this._deleted = false;
this._initializationPromise = null;
this._popupRedirectResolver = null;
this._errorFactory = _DEFAULT_AUTH_ERROR_FACTORY;
this._agentRecaptchaConfig = null;
this._tenantRecaptchaConfigs = {};
this._projectPasswordPolicy = null;
this._tenantPasswordPolicies = {};
this._resolvePersistenceManagerAvailable = void 0;
this.lastNotifiedUid = void 0;
this.languageCode = null;
this.tenantId = null;
this.settings = { appVerificationDisabledForTesting: false };
this.frameworks = [];
this.name = app2.name;
this.clientVersion = config.sdkClientVersion;
this._persistenceManagerAvailable = new Promise((resolve) => this._resolvePersistenceManagerAvailable = resolve);
}
_initializeWithPersistence(persistenceHierarchy, popupRedirectResolver) {
if (popupRedirectResolver) {
this._popupRedirectResolver = _getInstance(popupRedirectResolver);
}
this._initializationPromise = this.queue(async () => {
if (this._deleted) {
return;
}
this.persistenceManager = await PersistenceUserManager.create(this, persistenceHierarchy);
this._resolvePersistenceManagerAvailable?.();
if (this._deleted) {
return;
}
if (this._popupRedirectResolver?._shouldInitProactively) {
try {
await this._popupRedirectResolver._initialize(this);
} catch (e) {
}
}
await this.initializeCurrentUser(popupRedirectResolver);
this.lastNotifiedUid = this.currentUser?.uid || null;
if (this._deleted) {
return;
}
this._isInitialized = true;
});
return this._initializationPromise;
}
/**
* If the persistence is changed in another window, the user manager will let us know
*/
async _onStorageEvent() {
if (this._deleted) {
return;
}
const user = await this.assertedPersistence.getCurrentUser();
if (!this.currentUser && !user) {
return;
}
if (this.currentUser && user && this.currentUser.uid === user.uid) {
this._currentUser._assign(user);
await this.currentUser.getIdToken();
return;
}
await this._updateCurrentUser(
user,
/* skipBeforeStateCallbacks */
true
);
}
async initializeCurrentUserFromIdToken(idToken) {
try {
const response = await getAccountInfo(this, { idToken });
const user = await UserImpl._fromGetAccountInfoResponse(this, response, idToken);
await this.directlySetCurrentUser(user);
} catch (err) {
console.warn("FirebaseServerApp could not login user with provided authIdToken: ", err);
await this.directlySetCurrentUser(null);
}
}
async initializeCurrentUser(popupRedirectResolver) {
if (_isFirebaseServerApp(this.app)) {
const idToken = this.app.settings.authIdToken;
if (idToken) {
return new Promise((resolve) => {
setTimeout(() => this.initializeCurrentUserFromIdToken(idToken).then(resolve, resolve));
});
} else {
return this.directlySetCurrentUser(null);
}
}
const previouslyStoredUser = await this.assertedPersistence.getCurrentUser();
let futureCurrentUser = previouslyStoredUser;
let needsTocheckMiddleware = false;
if (popupRedirectResolver && this.config.authDomain) {
await this.getOrInitRedirectPersistenceManager();
const redirectUserEventId = this.redirectUser?._redirectEventId;
const storedUserEventId = futureCurrentUser?._redirectEventId;
const result = await this.tryRedirectSignIn(popupRedirectResolver);
if ((!redirectUserEventId || redirectUserEventId === storedUserEventId) && result?.user) {
futureCurrentUser = result.user;
needsTocheckMiddleware = true;
}
}
if (!futureCurrentUser) {
return this.directlySetCurrentUser(null);
}
if (!futureCurrentUser._redirectEventId) {
if (needsTocheckMiddleware) {
try {
await this.beforeStateQueue.runMiddleware(futureCurrentUser);
} catch (e) {
futureCurrentUser = previouslyStoredUser;
this._popupRedirectResolver._overrideRedirectResult(this, () => Promise.reject(e));
}
}
if (futureCurrentUser) {
return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
} else {
return this.directlySetCurrentUser(null);
}
}
_assert(
this._popupRedirectResolver,
this,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
await this.getOrInitRedirectPersistenceManager();
if (this.redirectUser && this.redirectUser._redirectEventId === futureCurrentUser._redirectEventId) {
return this.directlySetCurrentUser(futureCurrentUser);
}
return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
}
async tryRedirectSignIn(redirectResolver) {
let result = null;
try {
result = await this._popupRedirectResolver._completeRedirectFn(this, redirectResolver, true);
} catch (e) {
await this._setRedirectUser(null);
}
return result;
}
async reloadAndSetCurrentUserOrClear(user) {
try {
await _reloadWithoutSaving(user);
} catch (e) {
if (e?.code !== `auth/${"network-request-failed"}`) {
return this.directlySetCurrentUser(null);
}
}
return this.directlySetCurrentUser(user);
}
useDeviceLanguage() {
this.languageCode = _getUserLanguage();
}
async _delete() {
this._deleted = true;
}
async updateCurrentUser(userExtern) {
if (_isFirebaseServerApp(this.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this));
}
const user = userExtern ? getModularInstance(userExtern) : null;
if (user) {
_assert(
user.auth.config.apiKey === this.config.apiKey,
this,
"invalid-user-token"
/* AuthErrorCode.INVALID_AUTH */
);
}
return this._updateCurrentUser(user && user._clone(this));
}
async _updateCurrentUser(user, skipBeforeStateCallbacks = false) {
if (this._deleted) {
return;
}
if (user) {
_assert(
this.tenantId === user.tenantId,
this,
"tenant-id-mismatch"
/* AuthErrorCode.TENANT_ID_MISMATCH */
);
}
if (!skipBeforeStateCallbacks) {
await this.beforeStateQueue.runMiddleware(user);
}
return this.queue(async () => {
await this.directlySetCurrentUser(user);
this.notifyAuthListeners();
});
}
async signOut() {
if (_isFirebaseServerApp(this.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this));
}
await this.beforeStateQueue.runMiddleware(null);
if (this.redirectPersistenceManager || this._popupRedirectResolver) {
await this._setRedirectUser(null);
}
return this._updateCurrentUser(
null,
/* skipBeforeStateCallbacks */
true
);
}
setPersistence(persistence) {
if (_isFirebaseServerApp(this.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError(this));
}
return this.queue(async () => {
await this.assertedPersistence.setPersistence(_getInstance(persistence));
});
}
_getRecaptchaConfig() {
if (this.tenantId == null) {
return this._agentRecaptchaConfig;
} else {
return this._tenantRecaptchaConfigs[this.tenantId];
}
}
async validatePassword(password) {
if (!this._getPasswordPolicyInternal()) {
await this._updatePasswordPolicy();
}
const passwordPolicy = this._getPasswordPolicyInternal();
if (passwordPolicy.schemaVersion !== this.EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION) {
return Promise.reject(this._errorFactory.create("unsupported-password-policy-schema-version", {}));
}
return passwordPolicy.validatePassword(password);
}
_getPasswordPolicyInternal() {
if (this.tenantId === null) {
return this._projectPasswordPolicy;
} else {
return this._tenantPasswordPolicies[this.tenantId];
}
}
async _updatePasswordPolicy() {
const response = await _getPasswordPolicy(this);
const passwordPolicy = new PasswordPolicyImpl(response);
if (this.tenantId === null) {
this._projectPasswordPolicy = passwordPolicy;
} else {
this._tenantPasswordPolicies[this.tenantId] = passwordPolicy;
}
}
_getPersistenceType() {
return this.assertedPersistence.persistence.type;
}
_getPersistence() {
return this.assertedPersistence.persistence;
}
_updateErrorMap(errorMap) {
this._errorFactory = new ErrorFactory("auth", "Firebase", errorMap());
}
onAuthStateChanged(nextOrObserver, error, completed) {
return this.registerStateListener(this.authStateSubscription, nextOrObserver, error, completed);
}
beforeAuthStateChanged(callback, onAbort) {
return this.beforeStateQueue.pushCallback(callback, onAbort);
}
onIdTokenChanged(nextOrObserver, error, completed) {
return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
}
authStateReady() {
return new Promise((resolve, reject) => {
if (this.currentUser) {
resolve();
} else {
const unsubscribe = this.onAuthStateChanged(() => {
unsubscribe();
resolve();
}, reject);
}
});
}
/**
* Revokes the given access token. Currently only supports Apple OAuth access tokens.
*/
async revokeAccessToken(token) {
if (this.currentUser) {
const idToken = await this.currentUser.getIdToken();
const request = {
providerId: "apple.com",
tokenType: "ACCESS_TOKEN",
token,
idToken
};
if (this.tenantId != null) {
request.tenantId = this.tenantId;
}
await revokeToken(this, request);
}
}
toJSON() {
return {
apiKey: this.config.apiKey,
authDomain: this.config.authDomain,
appName: this.name,
currentUser: this._currentUser?.toJSON()
};
}
async _setRedirectUser(user, popupRedirectResolver) {
const redirectManager = await this.getOrInitRedirectPersistenceManager(popupRedirectResolver);
return user === null ? redirectManager.removeCurrentUser() : redirectManager.setCurrentUser(user);
}
async getOrInitRedirectPersistenceManager(popupRedirectResolver) {
if (!this.redirectPersistenceManager) {
const resolver = popupRedirectResolver && _getInstance(popupRedirectResolver) || this._popupRedirectResolver;
_assert(
resolver,
this,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
this.redirectPersistenceManager = await PersistenceUserManager.create(
this,
[_getInstance(resolver._redirectPersistence)],
"redirectUser"
/* KeyName.REDIRECT_USER */
);
this.redirectUser = await this.redirectPersistenceManager.getCurrentUser();
}
return this.redirectPersistenceManager;
}
async _redirectUserForId(id) {
if (this._isInitialized) {
await this.queue(async () => {
});
}
if (this._currentUser?._redirectEventId === id) {
return this._currentUser;
}
if (this.redirectUser?._redirectEventId === id) {
return this.redirectUser;
}
return null;
}
async _persistUserIfCurrent(user) {
if (user === this.currentUser) {
return this.queue(async () => this.directlySetCurrentUser(user));
}
}
/** Notifies listeners only if the user is current */
_notifyListenersIfCurrent(user) {
if (user === this.currentUser) {
this.notifyAuthListeners();
}
}
_key() {
return `${this.config.authDomain}:${this.config.apiKey}:${this.name}`;
}
_startProactiveRefresh() {
this.isProactiveRefreshEnabled = true;
if (this.currentUser) {
this._currentUser._startProactiveRefresh();
}
}
_stopProactiveRefresh() {
this.isProactiveRefreshEnabled = false;
if (this.currentUser) {
this._currentUser._stopProactiveRefresh();
}
}
/** Returns the current user cast as the internal type */
get _currentUser() {
return this.currentUser;
}
notifyAuthListeners() {
if (!this._isInitialized) {
return;
}
this.idTokenSubscription.next(this.currentUser);
const currentUid = this.currentUser?.uid ?? null;
if (this.lastNotifiedUid !== currentUid) {
this.lastNotifiedUid = currentUid;
this.authStateSubscription.next(this.currentUser);
}
}
registerStateListener(subscription, nextOrObserver, error, completed) {
if (this._deleted) {
return () => {
};
}
const cb = typeof nextOrObserver === "function" ? nextOrObserver : nextOrObserver.next.bind(nextOrObserver);
let isUnsubscribed = false;
const promise = this._isInitialized ? Promise.resolve() : this._initializationPromise;
_assert(
promise,
this,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
promise.then(() => {
if (isUnsubscribed) {
return;
}
cb(this.currentUser);
});
if (typeof nextOrObserver === "function") {
const unsubscribe = subscription.addObserver(nextOrObserver, error, completed);
return () => {
isUnsubscribed = true;
unsubscribe();
};
} else {
const unsubscribe = subscription.addObserver(nextOrObserver);
return () => {
isUnsubscribed = true;
unsubscribe();
};
}
}
/**
* Unprotected (from race conditions) method to set the current user. This
* should only be called from within a queued callback. This is necessary
* because the queue shouldn't rely on another queued callback.
*/
async directlySetCurrentUser(user) {
if (this.currentUser && this.currentUser !== user) {
this._currentUser._stopProactiveRefresh();
}
if (user && this.isProactiveRefreshEnabled) {
user._startProactiveRefresh();
}
this.currentUser = user;
if (user) {
await this.assertedPersistence.setCurrentUser(user);
} else {
await this.assertedPersistence.removeCurrentUser();
}
}
queue(action) {
this.operations = this.operations.then(action, action);
return this.operations;
}
get assertedPersistence() {
_assert(
this.persistenceManager,
this,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return this.persistenceManager;
}
_logFramework(framework) {
if (!framework || this.frameworks.includes(framework)) {
return;
}
this.frameworks.push(framework);
this.frameworks.sort();
this.clientVersion = _getClientVersion(this.config.clientPlatform, this._getFrameworks());
}
_getFrameworks() {
return this.frameworks;
}
async _getAdditionalHeaders() {
const headers = {
[
"X-Client-Version"
/* HttpHeader.X_CLIENT_VERSION */
]: this.clientVersion
};
if (this.app.options.appId) {
headers[
"X-Firebase-gmpid"
/* HttpHeader.X_FIREBASE_GMPID */
] = this.app.options.appId;
}
const heartbeatsHeader = await this.heartbeatServiceProvider.getImmediate({
optional: true
})?.getHeartbeatsHeader();
if (heartbeatsHeader) {
headers[
"X-Firebase-Client"
/* HttpHeader.X_FIREBASE_CLIENT */
] = heartbeatsHeader;
}
const appCheckToken = await this._getAppCheckToken();
if (appCheckToken) {
headers[
"X-Firebase-AppCheck"
/* HttpHeader.X_FIREBASE_APP_CHECK */
] = appCheckToken;
}
return headers;
}
async _getAppCheckToken() {
if (_isFirebaseServerApp(this.app) && this.app.settings.appCheckToken) {
return this.app.settings.appCheckToken;
}
const appCheckTokenResult = await this.appCheckServiceProvider.getImmediate({ optional: true })?.getToken();
if (appCheckTokenResult?.error) {
_logWarn(`Error while retrieving App Check token: ${appCheckTokenResult.error}`);
}
return appCheckTokenResult?.token;
}
};
Subscription = class {
constructor(auth2) {
this.auth = auth2;
this.observer = null;
this.addObserver = createSubscribe((observer) => this.observer = observer);
}
get next() {
_assert(
this.observer,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return this.observer.next.bind(this.observer);
}
};
externalJSProvider = {
async loadJS() {
throw new Error("Unable to load external scripts");
},
recaptchaV2Script: "",
recaptchaEnterpriseScript: "",
gapiScript: ""
};
MockGreCAPTCHATopLevel = class {
constructor() {
this.enterprise = new MockGreCAPTCHA();
}
ready(callback) {
callback();
}
execute(_siteKey, _options) {
return Promise.resolve("token");
}
render(_container, _parameters) {
return "";
}
};
MockGreCAPTCHA = class {
ready(callback) {
callback();
}
execute(_siteKey, _options) {
return Promise.resolve("token");
}
render(_container, _parameters) {
return "";
}
};
RECAPTCHA_ENTERPRISE_VERIFIER_TYPE = "recaptcha-enterprise";
FAKE_TOKEN = "NO_RECAPTCHA";
RecaptchaEnterpriseVerifier = class {
/**
*
* @param authExtern - The corresponding Firebase {@link Auth} instance.
*
*/
constructor(authExtern) {
this.type = RECAPTCHA_ENTERPRISE_VERIFIER_TYPE;
this.auth = _castAuth(authExtern);
}
/**
* Executes the verification process.
*
* @returns A Promise for a token that can be used to assert the validity of a request.
*/
async verify(action = "verify", forceRefresh = false) {
async function retrieveSiteKey(auth2) {
if (!forceRefresh) {
if (auth2.tenantId == null && auth2._agentRecaptchaConfig != null) {
return auth2._agentRecaptchaConfig.siteKey;
}
if (auth2.tenantId != null && auth2._tenantRecaptchaConfigs[auth2.tenantId] !== void 0) {
return auth2._tenantRecaptchaConfigs[auth2.tenantId].siteKey;
}
}
return new Promise(async (resolve, reject) => {
getRecaptchaConfig(auth2, {
clientType: "CLIENT_TYPE_WEB",
version: "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
}).then((response) => {
if (response.recaptchaKey === void 0) {
reject(new Error("recaptcha Enterprise site key undefined"));
} else {
const config = new RecaptchaConfig(response);
if (auth2.tenantId == null) {
auth2._agentRecaptchaConfig = config;
} else {
auth2._tenantRecaptchaConfigs[auth2.tenantId] = config;
}
return resolve(config.siteKey);
}
}).catch((error) => {
reject(error);
});
});
}
function retrieveRecaptchaToken(siteKey, resolve, reject) {
const grecaptcha = window.grecaptcha;
if (isEnterprise(grecaptcha)) {
grecaptcha.enterprise.ready(() => {
grecaptcha.enterprise.execute(siteKey, { action }).then((token) => {
resolve(token);
}).catch(() => {
resolve(FAKE_TOKEN);
});
});
} else {
reject(Error("No reCAPTCHA enterprise script loaded."));
}
}
if (this.auth.settings.appVerificationDisabledForTesting) {
const mockRecaptcha = new MockGreCAPTCHATopLevel();
return mockRecaptcha.execute("siteKey", { action: "verify" });
}
return new Promise((resolve, reject) => {
retrieveSiteKey(this.auth).then((siteKey) => {
if (!forceRefresh && isEnterprise(window.grecaptcha)) {
retrieveRecaptchaToken(siteKey, resolve, reject);
} else {
if (typeof window === "undefined") {
reject(new Error("RecaptchaVerifier is only supported in browser"));
return;
}
let url = _recaptchaEnterpriseScriptUrl();
if (url.length !== 0) {
url += siteKey;
}
_loadJS(url).then(() => {
retrieveRecaptchaToken(siteKey, resolve, reject);
}).catch((error) => {
reject(error);
});
}
}).catch((error) => {
reject(error);
});
});
}
};
AuthCredential = class {
/** @internal */
constructor(providerId, signInMethod) {
this.providerId = providerId;
this.signInMethod = signInMethod;
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns a JSON-serializable representation of this object.
*/
toJSON() {
return debugFail("not implemented");
}
/** @internal */
_getIdTokenResponse(_auth) {
return debugFail("not implemented");
}
/** @internal */
_linkToIdToken(_auth, _idToken) {
return debugFail("not implemented");
}
/** @internal */
_getReauthenticationResolver(_auth) {
return debugFail("not implemented");
}
};
EmailAuthCredential = class _EmailAuthCredential extends AuthCredential {
/** @internal */
constructor(_email, _password, signInMethod, _tenantId = null) {
super("password", signInMethod);
this._email = _email;
this._password = _password;
this._tenantId = _tenantId;
}
/** @internal */
static _fromEmailAndPassword(email, password) {
return new _EmailAuthCredential(
email,
password,
"password"
/* SignInMethod.EMAIL_PASSWORD */
);
}
/** @internal */
static _fromEmailAndCode(email, oobCode, tenantId = null) {
return new _EmailAuthCredential(email, oobCode, "emailLink", tenantId);
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
return {
email: this._email,
password: this._password,
signInMethod: this.signInMethod,
tenantId: this._tenantId
};
}
/**
* Static method to deserialize a JSON representation of an object into an {@link AuthCredential}.
*
* @param json - Either `object` or the stringified representation of the object. When string is
* provided, `JSON.parse` would be called first.
*
* @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
*/
static fromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
if (obj?.email && obj?.password) {
if (obj.signInMethod === "password") {
return this._fromEmailAndPassword(obj.email, obj.password);
} else if (obj.signInMethod === "emailLink") {
return this._fromEmailAndCode(obj.email, obj.password, obj.tenantId);
}
}
return null;
}
/** @internal */
async _getIdTokenResponse(auth2) {
switch (this.signInMethod) {
case "password":
const request = {
returnSecureToken: true,
email: this._email,
password: this._password,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
return handleRecaptchaFlow(
auth2,
request,
"signInWithPassword",
signInWithPassword,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
case "emailLink":
return signInWithEmailLink$1(auth2, {
email: this._email,
oobCode: this._password
});
default:
_fail(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
}
/** @internal */
async _linkToIdToken(auth2, idToken) {
switch (this.signInMethod) {
case "password":
const request = {
idToken,
returnSecureToken: true,
email: this._email,
password: this._password,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
return handleRecaptchaFlow(
auth2,
request,
"signUpPassword",
linkEmailPassword,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
case "emailLink":
return signInWithEmailLinkForLinking(auth2, {
idToken,
email: this._email,
oobCode: this._password
});
default:
_fail(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
}
/** @internal */
_getReauthenticationResolver(auth2) {
return this._getIdTokenResponse(auth2);
}
};
IDP_REQUEST_URI$1 = "http://localhost";
OAuthCredential = class _OAuthCredential extends AuthCredential {
constructor() {
super(...arguments);
this.pendingToken = null;
}
/** @internal */
static _fromParams(params) {
const cred = new _OAuthCredential(params.providerId, params.signInMethod);
if (params.idToken || params.accessToken) {
if (params.idToken) {
cred.idToken = params.idToken;
}
if (params.accessToken) {
cred.accessToken = params.accessToken;
}
if (params.nonce && !params.pendingToken) {
cred.nonce = params.nonce;
}
if (params.pendingToken) {
cred.pendingToken = params.pendingToken;
}
} else if (params.oauthToken && params.oauthTokenSecret) {
cred.accessToken = params.oauthToken;
cred.secret = params.oauthTokenSecret;
} else {
_fail(
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
}
return cred;
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
return {
idToken: this.idToken,
accessToken: this.accessToken,
secret: this.secret,
nonce: this.nonce,
pendingToken: this.pendingToken,
providerId: this.providerId,
signInMethod: this.signInMethod
};
}
/**
* Static method to deserialize a JSON representation of an object into an
* {@link AuthCredential}.
*
* @param json - Input can be either Object or the stringified representation of the object.
* When string is provided, JSON.parse would be called first.
*
* @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
*/
static fromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
const { providerId, signInMethod, ...rest } = obj;
if (!providerId || !signInMethod) {
return null;
}
const cred = new _OAuthCredential(providerId, signInMethod);
cred.idToken = rest.idToken || void 0;
cred.accessToken = rest.accessToken || void 0;
cred.secret = rest.secret;
cred.nonce = rest.nonce;
cred.pendingToken = rest.pendingToken || null;
return cred;
}
/** @internal */
_getIdTokenResponse(auth2) {
const request = this.buildRequest();
return signInWithIdp(auth2, request);
}
/** @internal */
_linkToIdToken(auth2, idToken) {
const request = this.buildRequest();
request.idToken = idToken;
return signInWithIdp(auth2, request);
}
/** @internal */
_getReauthenticationResolver(auth2) {
const request = this.buildRequest();
request.autoCreate = false;
return signInWithIdp(auth2, request);
}
buildRequest() {
const request = {
requestUri: IDP_REQUEST_URI$1,
returnSecureToken: true
};
if (this.pendingToken) {
request.pendingToken = this.pendingToken;
} else {
const postBody = {};
if (this.idToken) {
postBody["id_token"] = this.idToken;
}
if (this.accessToken) {
postBody["access_token"] = this.accessToken;
}
if (this.secret) {
postBody["oauth_token_secret"] = this.secret;
}
postBody["providerId"] = this.providerId;
if (this.nonce && !this.pendingToken) {
postBody["nonce"] = this.nonce;
}
request.postBody = querystring(postBody);
}
return request;
}
};
VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_ = {
[
"USER_NOT_FOUND"
/* ServerError.USER_NOT_FOUND */
]: "user-not-found"
/* AuthErrorCode.USER_DELETED */
};
PhoneAuthCredential = class _PhoneAuthCredential extends AuthCredential {
constructor(params) {
super(
"phone",
"phone"
/* SignInMethod.PHONE */
);
this.params = params;
}
/** @internal */
static _fromVerification(verificationId, verificationCode) {
return new _PhoneAuthCredential({ verificationId, verificationCode });
}
/** @internal */
static _fromTokenResponse(phoneNumber, temporaryProof) {
return new _PhoneAuthCredential({ phoneNumber, temporaryProof });
}
/** @internal */
_getIdTokenResponse(auth2) {
return signInWithPhoneNumber$1(auth2, this._makeVerificationRequest());
}
/** @internal */
_linkToIdToken(auth2, idToken) {
return linkWithPhoneNumber$1(auth2, {
idToken,
...this._makeVerificationRequest()
});
}
/** @internal */
_getReauthenticationResolver(auth2) {
return verifyPhoneNumberForExisting(auth2, this._makeVerificationRequest());
}
/** @internal */
_makeVerificationRequest() {
const { temporaryProof, phoneNumber, verificationId, verificationCode } = this.params;
if (temporaryProof && phoneNumber) {
return { temporaryProof, phoneNumber };
}
return {
sessionInfo: verificationId,
code: verificationCode
};
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
const obj = {
providerId: this.providerId
};
if (this.params.phoneNumber) {
obj.phoneNumber = this.params.phoneNumber;
}
if (this.params.temporaryProof) {
obj.temporaryProof = this.params.temporaryProof;
}
if (this.params.verificationCode) {
obj.verificationCode = this.params.verificationCode;
}
if (this.params.verificationId) {
obj.verificationId = this.params.verificationId;
}
return obj;
}
/** Generates a phone credential based on a plain object or a JSON string. */
static fromJSON(json) {
if (typeof json === "string") {
json = JSON.parse(json);
}
const { verificationId, verificationCode, phoneNumber, temporaryProof } = json;
if (!verificationCode && !verificationId && !phoneNumber && !temporaryProof) {
return null;
}
return new _PhoneAuthCredential({
verificationId,
verificationCode,
phoneNumber,
temporaryProof
});
}
};
ActionCodeURL = class _ActionCodeURL {
/**
* @param actionLink - The link from which to extract the URL.
* @returns The {@link ActionCodeURL} object, or null if the link is invalid.
*
* @internal
*/
constructor(actionLink) {
const searchParams = querystringDecode(extractQuerystring(actionLink));
const apiKey = searchParams[
"apiKey"
/* QueryField.API_KEY */
] ?? null;
const code = searchParams[
"oobCode"
/* QueryField.CODE */
] ?? null;
const operation = parseMode(searchParams[
"mode"
/* QueryField.MODE */
] ?? null);
_assert(
apiKey && code && operation,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
this.apiKey = apiKey;
this.operation = operation;
this.code = code;
this.continueUrl = searchParams[
"continueUrl"
/* QueryField.CONTINUE_URL */
] ?? null;
this.languageCode = searchParams[
"lang"
/* QueryField.LANGUAGE_CODE */
] ?? null;
this.tenantId = searchParams[
"tenantId"
/* QueryField.TENANT_ID */
] ?? null;
}
/**
* Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid,
* otherwise returns null.
*
* @param link - The email action link string.
* @returns The {@link ActionCodeURL} object, or null if the link is invalid.
*
* @public
*/
static parseLink(link) {
const actionLink = parseDeepLink(link);
try {
return new _ActionCodeURL(actionLink);
} catch {
return null;
}
}
};
EmailAuthProvider = class _EmailAuthProvider {
constructor() {
this.providerId = _EmailAuthProvider.PROVIDER_ID;
}
/**
* Initialize an {@link AuthCredential} using an email and password.
*
* @example
* ```javascript
* const authCredential = EmailAuthProvider.credential(email, password);
* const userCredential = await signInWithCredential(auth, authCredential);
* ```
*
* @example
* ```javascript
* const userCredential = await signInWithEmailAndPassword(auth, email, password);
* ```
*
* @param email - Email address.
* @param password - User account password.
* @returns The auth provider credential.
*/
static credential(email, password) {
return EmailAuthCredential._fromEmailAndPassword(email, password);
}
/**
* Initialize an {@link AuthCredential} using an email and an email link after a sign in with
* email link operation.
*
* @example
* ```javascript
* const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink);
* const userCredential = await signInWithCredential(auth, authCredential);
* ```
*
* @example
* ```javascript
* await sendSignInLinkToEmail(auth, email);
* // Obtain emailLink from user.
* const userCredential = await signInWithEmailLink(auth, email, emailLink);
* ```
*
* @param auth - The {@link Auth} instance used to verify the link.
* @param email - Email address.
* @param emailLink - Sign-in email link.
* @returns - The auth provider credential.
*/
static credentialWithLink(email, emailLink) {
const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
_assert(
actionCodeUrl,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return EmailAuthCredential._fromEmailAndCode(email, actionCodeUrl.code, actionCodeUrl.tenantId);
}
};
EmailAuthProvider.PROVIDER_ID = "password";
EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD = "password";
EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD = "emailLink";
FederatedAuthProvider = class {
/**
* Constructor for generic OAuth providers.
*
* @param providerId - Provider for which credentials should be generated.
*/
constructor(providerId) {
this.providerId = providerId;
this.defaultLanguageCode = null;
this.customParameters = {};
}
/**
* Set the language gode.
*
* @param languageCode - language code
*/
setDefaultLanguage(languageCode) {
this.defaultLanguageCode = languageCode;
}
/**
* Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in
* operations.
*
* @remarks
* For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`,
* `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored.
*
* @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request.
*/
setCustomParameters(customOAuthParameters) {
this.customParameters = customOAuthParameters;
return this;
}
/**
* Retrieve the current list of {@link CustomParameters}.
*/
getCustomParameters() {
return this.customParameters;
}
};
BaseOAuthProvider = class extends FederatedAuthProvider {
constructor() {
super(...arguments);
this.scopes = [];
}
/**
* Add an OAuth scope to the credential.
*
* @param scope - Provider OAuth scope to add.
*/
addScope(scope) {
if (!this.scopes.includes(scope)) {
this.scopes.push(scope);
}
return this;
}
/**
* Retrieve the current list of OAuth scopes.
*/
getScopes() {
return [...this.scopes];
}
};
OAuthProvider = class _OAuthProvider extends BaseOAuthProvider {
/**
* Creates an {@link OAuthCredential} from a JSON string or a plain object.
* @param json - A plain object or a JSON string
*/
static credentialFromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
_assert(
"providerId" in obj && "signInMethod" in obj,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return OAuthCredential._fromParams(obj);
}
/**
* Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token.
*
* @remarks
* The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of
* the raw nonce must match the nonce field in the ID token.
*
* @example
* ```javascript
* // `googleUser` from the onsuccess Google Sign In callback.
* // Initialize a generate OAuth provider with a `google.com` providerId.
* const provider = new OAuthProvider('google.com');
* const credential = provider.credential({
* idToken: googleUser.getAuthResponse().id_token,
* });
* const result = await signInWithCredential(credential);
* ```
*
* @param params - Either the options object containing the ID token, access token and raw nonce
* or the ID token string.
*/
credential(params) {
return this._credential({ ...params, nonce: params.rawNonce });
}
/** An internal credential method that accepts more permissive options */
_credential(params) {
_assert(
params.idToken || params.accessToken,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return OAuthCredential._fromParams({
...params,
providerId: this.providerId,
signInMethod: this.providerId
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _OAuthProvider.oauthCredentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _OAuthProvider.oauthCredentialFromTaggedObject(error.customData || {});
}
static oauthCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { oauthIdToken, oauthAccessToken, oauthTokenSecret, pendingToken, nonce, providerId } = tokenResponse;
if (!oauthAccessToken && !oauthTokenSecret && !oauthIdToken && !pendingToken) {
return null;
}
if (!providerId) {
return null;
}
try {
return new _OAuthProvider(providerId)._credential({
idToken: oauthIdToken,
accessToken: oauthAccessToken,
nonce,
pendingToken
});
} catch (e) {
return null;
}
}
};
FacebookAuthProvider = class _FacebookAuthProvider extends BaseOAuthProvider {
constructor() {
super(
"facebook.com"
/* ProviderId.FACEBOOK */
);
}
/**
* Creates a credential for Facebook.
*
* @example
* ```javascript
* // `event` from the Facebook auth.authResponseChange callback.
* const credential = FacebookAuthProvider.credential(event.authResponse.accessToken);
* const result = await signInWithCredential(credential);
* ```
*
* @param accessToken - Facebook access token.
*/
static credential(accessToken) {
return OAuthCredential._fromParams({
providerId: _FacebookAuthProvider.PROVIDER_ID,
signInMethod: _FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD,
accessToken
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _FacebookAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _FacebookAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse || !("oauthAccessToken" in tokenResponse)) {
return null;
}
if (!tokenResponse.oauthAccessToken) {
return null;
}
try {
return _FacebookAuthProvider.credential(tokenResponse.oauthAccessToken);
} catch {
return null;
}
}
};
FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD = "facebook.com";
FacebookAuthProvider.PROVIDER_ID = "facebook.com";
GoogleAuthProvider = class _GoogleAuthProvider extends BaseOAuthProvider {
constructor() {
super(
"google.com"
/* ProviderId.GOOGLE */
);
this.addScope("profile");
}
/**
* Creates a credential for Google. At least one of ID token and access token is required.
*
* @example
* ```javascript
* // \`googleUser\` from the onsuccess Google Sign In callback.
* const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
* const result = await signInWithCredential(credential);
* ```
*
* @param idToken - Google ID token.
* @param accessToken - Google access token.
*/
static credential(idToken, accessToken) {
return OAuthCredential._fromParams({
providerId: _GoogleAuthProvider.PROVIDER_ID,
signInMethod: _GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD,
idToken,
accessToken
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _GoogleAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _GoogleAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { oauthIdToken, oauthAccessToken } = tokenResponse;
if (!oauthIdToken && !oauthAccessToken) {
return null;
}
try {
return _GoogleAuthProvider.credential(oauthIdToken, oauthAccessToken);
} catch {
return null;
}
}
};
GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD = "google.com";
GoogleAuthProvider.PROVIDER_ID = "google.com";
GithubAuthProvider = class _GithubAuthProvider extends BaseOAuthProvider {
constructor() {
super(
"github.com"
/* ProviderId.GITHUB */
);
}
/**
* Creates a credential for GitHub.
*
* @param accessToken - GitHub access token.
*/
static credential(accessToken) {
return OAuthCredential._fromParams({
providerId: _GithubAuthProvider.PROVIDER_ID,
signInMethod: _GithubAuthProvider.GITHUB_SIGN_IN_METHOD,
accessToken
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _GithubAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _GithubAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse || !("oauthAccessToken" in tokenResponse)) {
return null;
}
if (!tokenResponse.oauthAccessToken) {
return null;
}
try {
return _GithubAuthProvider.credential(tokenResponse.oauthAccessToken);
} catch {
return null;
}
}
};
GithubAuthProvider.GITHUB_SIGN_IN_METHOD = "github.com";
GithubAuthProvider.PROVIDER_ID = "github.com";
IDP_REQUEST_URI = "http://localhost";
SAMLAuthCredential = class _SAMLAuthCredential extends AuthCredential {
/** @internal */
constructor(providerId, pendingToken) {
super(providerId, providerId);
this.pendingToken = pendingToken;
}
/** @internal */
_getIdTokenResponse(auth2) {
const request = this.buildRequest();
return signInWithIdp(auth2, request);
}
/** @internal */
_linkToIdToken(auth2, idToken) {
const request = this.buildRequest();
request.idToken = idToken;
return signInWithIdp(auth2, request);
}
/** @internal */
_getReauthenticationResolver(auth2) {
const request = this.buildRequest();
request.autoCreate = false;
return signInWithIdp(auth2, request);
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
return {
signInMethod: this.signInMethod,
providerId: this.providerId,
pendingToken: this.pendingToken
};
}
/**
* Static method to deserialize a JSON representation of an object into an
* {@link AuthCredential}.
*
* @param json - Input can be either Object or the stringified representation of the object.
* When string is provided, JSON.parse would be called first.
*
* @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
*/
static fromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
const { providerId, signInMethod, pendingToken } = obj;
if (!providerId || !signInMethod || !pendingToken || providerId !== signInMethod) {
return null;
}
return new _SAMLAuthCredential(providerId, pendingToken);
}
/**
* Helper static method to avoid exposing the constructor to end users.
*
* @internal
*/
static _create(providerId, pendingToken) {
return new _SAMLAuthCredential(providerId, pendingToken);
}
buildRequest() {
return {
requestUri: IDP_REQUEST_URI,
returnSecureToken: true,
pendingToken: this.pendingToken
};
}
};
SAML_PROVIDER_PREFIX = "saml.";
SAMLAuthProvider = class _SAMLAuthProvider extends FederatedAuthProvider {
/**
* Constructor. The providerId must start with "saml."
* @param providerId - SAML provider ID.
*/
constructor(providerId) {
_assert(
providerId.startsWith(SAML_PROVIDER_PREFIX),
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
super(providerId);
}
/**
* Generates an {@link AuthCredential} from a {@link UserCredential} after a
* successful SAML flow completes.
*
* @remarks
*
* For example, to get an {@link AuthCredential}, you could write the
* following code:
*
* ```js
* const userCredential = await signInWithPopup(auth, samlProvider);
* const credential = SAMLAuthProvider.credentialFromResult(userCredential);
* ```
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _SAMLAuthProvider.samlCredentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _SAMLAuthProvider.samlCredentialFromTaggedObject(error.customData || {});
}
/**
* Creates an {@link AuthCredential} from a JSON string or a plain object.
* @param json - A plain object or a JSON string
*/
static credentialFromJSON(json) {
const credential = SAMLAuthCredential.fromJSON(json);
_assert(
credential,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return credential;
}
static samlCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { pendingToken, providerId } = tokenResponse;
if (!pendingToken || !providerId) {
return null;
}
try {
return SAMLAuthCredential._create(providerId, pendingToken);
} catch (e) {
return null;
}
}
};
TwitterAuthProvider = class _TwitterAuthProvider extends BaseOAuthProvider {
constructor() {
super(
"twitter.com"
/* ProviderId.TWITTER */
);
}
/**
* Creates a credential for Twitter.
*
* @param token - Twitter access token.
* @param secret - Twitter secret.
*/
static credential(token, secret) {
return OAuthCredential._fromParams({
providerId: _TwitterAuthProvider.PROVIDER_ID,
signInMethod: _TwitterAuthProvider.TWITTER_SIGN_IN_METHOD,
oauthToken: token,
oauthTokenSecret: secret
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _TwitterAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _TwitterAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { oauthAccessToken, oauthTokenSecret } = tokenResponse;
if (!oauthAccessToken || !oauthTokenSecret) {
return null;
}
try {
return _TwitterAuthProvider.credential(oauthAccessToken, oauthTokenSecret);
} catch {
return null;
}
}
};
TwitterAuthProvider.TWITTER_SIGN_IN_METHOD = "twitter.com";
TwitterAuthProvider.PROVIDER_ID = "twitter.com";
UserCredentialImpl = class _UserCredentialImpl {
constructor(params) {
this.user = params.user;
this.providerId = params.providerId;
this._tokenResponse = params._tokenResponse;
this.operationType = params.operationType;
}
static async _fromIdTokenResponse(auth2, operationType, idTokenResponse, isAnonymous = false) {
const user = await UserImpl._fromIdTokenResponse(auth2, idTokenResponse, isAnonymous);
const providerId = providerIdForResponse(idTokenResponse);
const userCred = new _UserCredentialImpl({
user,
providerId,
_tokenResponse: idTokenResponse,
operationType
});
return userCred;
}
static async _forOperation(user, operationType, response) {
await user._updateTokensIfNecessary(
response,
/* reload */
true
);
const providerId = providerIdForResponse(response);
return new _UserCredentialImpl({
user,
providerId,
_tokenResponse: response,
operationType
});
}
};
MultiFactorError = class _MultiFactorError extends FirebaseError {
constructor(auth2, error, operationType, user) {
super(error.code, error.message);
this.operationType = operationType;
this.user = user;
Object.setPrototypeOf(this, _MultiFactorError.prototype);
this.customData = {
appName: auth2.name,
tenantId: auth2.tenantId ?? void 0,
_serverResponse: error.customData._serverResponse,
operationType
};
}
static _fromErrorAndOperation(auth2, error, operationType, user) {
return new _MultiFactorError(auth2, error, operationType, user);
}
};
MultiFactorInfoImpl = class {
constructor(factorId, response) {
this.factorId = factorId;
this.uid = response.mfaEnrollmentId;
this.enrollmentTime = new Date(response.enrolledAt).toUTCString();
this.displayName = response.displayName;
}
static _fromServerResponse(auth2, enrollment) {
if ("phoneInfo" in enrollment) {
return PhoneMultiFactorInfoImpl._fromServerResponse(auth2, enrollment);
} else if ("totpInfo" in enrollment) {
return TotpMultiFactorInfoImpl._fromServerResponse(auth2, enrollment);
}
return _fail(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
};
PhoneMultiFactorInfoImpl = class _PhoneMultiFactorInfoImpl extends MultiFactorInfoImpl {
constructor(response) {
super("phone", response);
this.phoneNumber = response.phoneInfo;
}
static _fromServerResponse(_auth, enrollment) {
return new _PhoneMultiFactorInfoImpl(enrollment);
}
};
TotpMultiFactorInfoImpl = class _TotpMultiFactorInfoImpl extends MultiFactorInfoImpl {
constructor(response) {
super("totp", response);
}
static _fromServerResponse(_auth, enrollment) {
return new _TotpMultiFactorInfoImpl(enrollment);
}
};
GenericAdditionalUserInfo = class {
constructor(isNewUser, providerId, profile = {}) {
this.isNewUser = isNewUser;
this.providerId = providerId;
this.profile = profile;
}
};
FederatedAdditionalUserInfoWithUsername = class extends GenericAdditionalUserInfo {
constructor(isNewUser, providerId, profile, username) {
super(isNewUser, providerId, profile);
this.username = username;
}
};
FacebookAdditionalUserInfo = class extends GenericAdditionalUserInfo {
constructor(isNewUser, profile) {
super(isNewUser, "facebook.com", profile);
}
};
GithubAdditionalUserInfo = class extends FederatedAdditionalUserInfoWithUsername {
constructor(isNewUser, profile) {
super(isNewUser, "github.com", profile, typeof profile?.login === "string" ? profile?.login : null);
}
};
GoogleAdditionalUserInfo = class extends GenericAdditionalUserInfo {
constructor(isNewUser, profile) {
super(isNewUser, "google.com", profile);
}
};
TwitterAdditionalUserInfo = class extends FederatedAdditionalUserInfoWithUsername {
constructor(isNewUser, profile, screenName) {
super(isNewUser, "twitter.com", profile, screenName);
}
};
MultiFactorSessionImpl = class _MultiFactorSessionImpl {
constructor(type, credential, user) {
this.type = type;
this.credential = credential;
this.user = user;
}
static _fromIdtoken(idToken, user) {
return new _MultiFactorSessionImpl("enroll", idToken, user);
}
static _fromMfaPendingCredential(mfaPendingCredential) {
return new _MultiFactorSessionImpl("signin", mfaPendingCredential);
}
toJSON() {
const key = this.type === "enroll" ? "idToken" : "pendingCredential";
return {
multiFactorSession: {
[key]: this.credential
}
};
}
static fromJSON(obj) {
if (obj?.multiFactorSession) {
if (obj.multiFactorSession?.pendingCredential) {
return _MultiFactorSessionImpl._fromMfaPendingCredential(obj.multiFactorSession.pendingCredential);
} else if (obj.multiFactorSession?.idToken) {
return _MultiFactorSessionImpl._fromIdtoken(obj.multiFactorSession.idToken);
}
}
return null;
}
};
MultiFactorResolverImpl = class _MultiFactorResolverImpl {
constructor(session, hints, signInResolver) {
this.session = session;
this.hints = hints;
this.signInResolver = signInResolver;
}
/** @internal */
static _fromError(authExtern, error) {
const auth2 = _castAuth(authExtern);
const serverResponse = error.customData._serverResponse;
const hints = (serverResponse.mfaInfo || []).map((enrollment) => MultiFactorInfoImpl._fromServerResponse(auth2, enrollment));
_assert(
serverResponse.mfaPendingCredential,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const session = MultiFactorSessionImpl._fromMfaPendingCredential(serverResponse.mfaPendingCredential);
return new _MultiFactorResolverImpl(session, hints, async (assertion) => {
const mfaResponse = await assertion._process(auth2, session);
delete serverResponse.mfaInfo;
delete serverResponse.mfaPendingCredential;
const idTokenResponse = {
...serverResponse,
idToken: mfaResponse.idToken,
refreshToken: mfaResponse.refreshToken
};
switch (error.operationType) {
case "signIn":
const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth2, error.operationType, idTokenResponse);
await auth2._updateCurrentUser(userCredential.user);
return userCredential;
case "reauthenticate":
_assert(
error.user,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return UserCredentialImpl._forOperation(error.user, error.operationType, idTokenResponse);
default:
_fail(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
});
}
async resolveSignIn(assertionExtern) {
const assertion = assertionExtern;
return this.signInResolver(assertion);
}
};
MultiFactorUserImpl = class _MultiFactorUserImpl {
constructor(user) {
this.user = user;
this.enrolledFactors = [];
user._onReload((userInfo) => {
if (userInfo.mfaInfo) {
this.enrolledFactors = userInfo.mfaInfo.map((enrollment) => MultiFactorInfoImpl._fromServerResponse(user.auth, enrollment));
}
});
}
static _fromUser(user) {
return new _MultiFactorUserImpl(user);
}
async getSession() {
return MultiFactorSessionImpl._fromIdtoken(await this.user.getIdToken(), this.user);
}
async enroll(assertionExtern, displayName) {
const assertion = assertionExtern;
const session = await this.getSession();
const finalizeMfaResponse = await _logoutIfInvalidated(this.user, assertion._process(this.user.auth, session, displayName));
await this.user._updateTokensIfNecessary(finalizeMfaResponse);
return this.user.reload();
}
async unenroll(infoOrUid) {
const mfaEnrollmentId = typeof infoOrUid === "string" ? infoOrUid : infoOrUid.uid;
const idToken = await this.user.getIdToken();
try {
const idTokenResponse = await _logoutIfInvalidated(this.user, withdrawMfa(this.user.auth, {
idToken,
mfaEnrollmentId
}));
this.enrolledFactors = this.enrolledFactors.filter(({ uid }) => uid !== mfaEnrollmentId);
await this.user._updateTokensIfNecessary(idTokenResponse);
await this.user.reload();
} catch (e) {
throw e;
}
}
};
multiFactorUserCache = /* @__PURE__ */ new WeakMap();
name3 = "@firebase/auth";
version3 = "1.11.1";
AuthInterop = class {
constructor(auth2) {
this.auth = auth2;
this.internalListeners = /* @__PURE__ */ new Map();
}
getUid() {
this.assertAuthConfigured();
return this.auth.currentUser?.uid || null;
}
async getToken(forceRefresh) {
this.assertAuthConfigured();
await this.auth._initializationPromise;
if (!this.auth.currentUser) {
return null;
}
const accessToken = await this.auth.currentUser.getIdToken(forceRefresh);
return { accessToken };
}
addAuthTokenListener(listener) {
this.assertAuthConfigured();
if (this.internalListeners.has(listener)) {
return;
}
const unsubscribe = this.auth.onIdTokenChanged((user) => {
listener(user?.stsTokenManager.accessToken || null);
});
this.internalListeners.set(listener, unsubscribe);
this.updateProactiveRefresh();
}
removeAuthTokenListener(listener) {
this.assertAuthConfigured();
const unsubscribe = this.internalListeners.get(listener);
if (!unsubscribe) {
return;
}
this.internalListeners.delete(listener);
unsubscribe();
this.updateProactiveRefresh();
}
assertAuthConfigured() {
_assert(
this.auth._initializationPromise,
"dependent-sdk-initialized-before-auth"
/* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
);
}
updateProactiveRefresh() {
if (this.internalListeners.size > 0) {
this.auth._startProactiveRefresh();
} else {
this.auth._stopProactiveRefresh();
}
}
};
FetchProvider.initialize(fetch, Headers, Response);
registerAuth(
"Node"
/* ClientPlatform.NODE */
);
NOT_AVAILABLE_ERROR = _createError(
"operation-not-supported-in-this-environment"
/* AuthErrorCode.OPERATION_NOT_SUPPORTED */
);
FailClass = class {
constructor() {
throw NOT_AVAILABLE_ERROR;
}
};
browserLocalPersistence = inMemoryPersistence;
browserSessionPersistence = inMemoryPersistence;
browserCookiePersistence = inMemoryPersistence;
indexedDBLocalPersistence = inMemoryPersistence;
browserPopupRedirectResolver = NOT_AVAILABLE_ERROR;
PhoneAuthProvider = FailClass;
signInWithPhoneNumber = fail;
linkWithPhoneNumber = fail;
reauthenticateWithPhoneNumber = fail;
updatePhoneNumber = fail;
signInWithPopup = fail;
linkWithPopup = fail;
reauthenticateWithPopup = fail;
signInWithRedirect = fail;
linkWithRedirect = fail;
reauthenticateWithRedirect = fail;
getRedirectResult = fail;
RecaptchaVerifier = FailClass;
PhoneMultiFactorGenerator = class {
static assertion() {
throw NOT_AVAILABLE_ERROR;
}
};
AuthImpl.prototype.setPersistence = async () => {
};
MultiFactorAssertionImpl = class {
constructor(factorId) {
this.factorId = factorId;
}
_process(auth2, session, displayName) {
switch (session.type) {
case "enroll":
return this._finalizeEnroll(auth2, session.credential, displayName);
case "signin":
return this._finalizeSignIn(auth2, session.credential);
default:
return debugFail("unexpected MultiFactorSessionType");
}
}
};
TotpMultiFactorGenerator = class {
/**
* Provides a {@link TotpMultiFactorAssertion} to confirm ownership of
* the TOTP (time-based one-time password) second factor.
* This assertion is used to complete enrollment in TOTP second factor.
*
* @param secret A {@link TotpSecret} containing the shared secret key and other TOTP parameters.
* @param oneTimePassword One-time password from TOTP App.
* @returns A {@link TotpMultiFactorAssertion} which can be used with
* {@link MultiFactorUser.enroll}.
*/
static assertionForEnrollment(secret, oneTimePassword) {
return TotpMultiFactorAssertionImpl._fromSecret(secret, oneTimePassword);
}
/**
* Provides a {@link TotpMultiFactorAssertion} to confirm ownership of the TOTP second factor.
* This assertion is used to complete signIn with TOTP as the second factor.
*
* @param enrollmentId identifies the enrolled TOTP second factor.
* @param oneTimePassword One-time password from TOTP App.
* @returns A {@link TotpMultiFactorAssertion} which can be used with
* {@link MultiFactorResolver.resolveSignIn}.
*/
static assertionForSignIn(enrollmentId, oneTimePassword) {
return TotpMultiFactorAssertionImpl._fromEnrollmentId(enrollmentId, oneTimePassword);
}
/**
* Returns a promise to {@link TotpSecret} which contains the TOTP shared secret key and other parameters.
* Creates a TOTP secret as part of enrolling a TOTP second factor.
* Used for generating a QR code URL or inputting into a TOTP app.
* This method uses the auth instance corresponding to the user in the multiFactorSession.
*
* @param session The {@link MultiFactorSession} that the user is part of.
* @returns A promise to {@link TotpSecret}.
*/
static async generateSecret(session) {
const mfaSession = session;
_assert(
typeof mfaSession.user?.auth !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const response = await startEnrollTotpMfa(mfaSession.user.auth, {
idToken: mfaSession.credential,
totpEnrollmentInfo: {}
});
return TotpSecret._fromStartTotpMfaEnrollmentResponse(response, mfaSession.user.auth);
}
};
TotpMultiFactorGenerator.FACTOR_ID = "totp";
TotpMultiFactorAssertionImpl = class _TotpMultiFactorAssertionImpl extends MultiFactorAssertionImpl {
constructor(otp, enrollmentId, secret) {
super(
"totp"
/* FactorId.TOTP */
);
this.otp = otp;
this.enrollmentId = enrollmentId;
this.secret = secret;
}
/** @internal */
static _fromSecret(secret, otp) {
return new _TotpMultiFactorAssertionImpl(otp, void 0, secret);
}
/** @internal */
static _fromEnrollmentId(enrollmentId, otp) {
return new _TotpMultiFactorAssertionImpl(otp, enrollmentId);
}
/** @internal */
async _finalizeEnroll(auth2, idToken, displayName) {
_assert(
typeof this.secret !== "undefined",
auth2,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return finalizeEnrollTotpMfa(auth2, {
idToken,
displayName,
totpVerificationInfo: this.secret._makeTotpVerificationInfo(this.otp)
});
}
/** @internal */
async _finalizeSignIn(auth2, mfaPendingCredential) {
_assert(
this.enrollmentId !== void 0 && this.otp !== void 0,
auth2,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
const totpVerificationInfo = { verificationCode: this.otp };
return finalizeSignInTotpMfa(auth2, {
mfaPendingCredential,
mfaEnrollmentId: this.enrollmentId,
totpVerificationInfo
});
}
};
TotpSecret = class _TotpSecret {
// The public members are declared outside the constructor so the docs can be generated.
constructor(secretKey, hashingAlgorithm, codeLength, codeIntervalSeconds, enrollmentCompletionDeadline, sessionInfo, auth2) {
this.sessionInfo = sessionInfo;
this.auth = auth2;
this.secretKey = secretKey;
this.hashingAlgorithm = hashingAlgorithm;
this.codeLength = codeLength;
this.codeIntervalSeconds = codeIntervalSeconds;
this.enrollmentCompletionDeadline = enrollmentCompletionDeadline;
}
/** @internal */
static _fromStartTotpMfaEnrollmentResponse(response, auth2) {
return new _TotpSecret(response.totpSessionInfo.sharedSecretKey, response.totpSessionInfo.hashingAlgorithm, response.totpSessionInfo.verificationCodeLength, response.totpSessionInfo.periodSec, new Date(response.totpSessionInfo.finalizeEnrollmentTime).toUTCString(), response.totpSessionInfo.sessionInfo, auth2);
}
/** @internal */
_makeTotpVerificationInfo(otp) {
return { sessionInfo: this.sessionInfo, verificationCode: otp };
}
/**
* Returns a QR code URL as described in
* https://github.com/google/google-authenticator/wiki/Key-Uri-Format
* This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator.
* If the optional parameters are unspecified, an accountName of <userEmail> and issuer of <firebaseAppName> are used.
*
* @param accountName the name of the account/app along with a user identifier.
* @param issuer issuer of the TOTP (likely the app name).
* @returns A QR code URL string.
*/
generateQrCodeUrl(accountName, issuer) {
let useDefaults = false;
if (_isEmptyString(accountName) || _isEmptyString(issuer)) {
useDefaults = true;
}
if (useDefaults) {
if (_isEmptyString(accountName)) {
accountName = this.auth.currentUser?.email || "unknownuser";
}
if (_isEmptyString(issuer)) {
issuer = this.auth.name;
}
}
return `otpauth://totp/${issuer}:${accountName}?secret=${this.secretKey}&issuer=${issuer}&algorithm=${this.hashingAlgorithm}&digits=${this.codeLength}`;
}
};
}
});
// node_modules/@firebase/auth/dist/node-esm/index.js
var init_node_esm = __esm({
"node_modules/@firebase/auth/dist/node-esm/index.js"() {
init_totp_c8d207b9();
init_index_esm3();
init_index_node_esm();
init_index_esm();
init_index_esm2();
}
});
// node_modules/firebase/auth/dist/index.mjs
var dist_exports = {};
__export(dist_exports, {
ActionCodeOperation: () => ActionCodeOperation,
ActionCodeURL: () => ActionCodeURL,
AuthCredential: () => AuthCredential,
AuthErrorCodes: () => AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY,
EmailAuthCredential: () => EmailAuthCredential,
EmailAuthProvider: () => EmailAuthProvider,
FacebookAuthProvider: () => FacebookAuthProvider,
FactorId: () => FactorId,
GithubAuthProvider: () => GithubAuthProvider,
GoogleAuthProvider: () => GoogleAuthProvider,
OAuthCredential: () => OAuthCredential,
OAuthProvider: () => OAuthProvider,
OperationType: () => OperationType,
PhoneAuthCredential: () => PhoneAuthCredential,
PhoneAuthProvider: () => PhoneAuthProvider,
PhoneMultiFactorGenerator: () => PhoneMultiFactorGenerator,
ProviderId: () => ProviderId,
RecaptchaVerifier: () => RecaptchaVerifier,
SAMLAuthProvider: () => SAMLAuthProvider,
SignInMethod: () => SignInMethod,
TotpMultiFactorGenerator: () => TotpMultiFactorGenerator,
TotpSecret: () => TotpSecret,
TwitterAuthProvider: () => TwitterAuthProvider,
applyActionCode: () => applyActionCode,
beforeAuthStateChanged: () => beforeAuthStateChanged,
browserCookiePersistence: () => browserCookiePersistence,
browserLocalPersistence: () => browserLocalPersistence,
browserPopupRedirectResolver: () => browserPopupRedirectResolver,
browserSessionPersistence: () => browserSessionPersistence,
checkActionCode: () => checkActionCode,
confirmPasswordReset: () => confirmPasswordReset,
connectAuthEmulator: () => connectAuthEmulator,
createUserWithEmailAndPassword: () => createUserWithEmailAndPassword,
debugErrorMap: () => debugErrorMap,
deleteUser: () => deleteUser,
fetchSignInMethodsForEmail: () => fetchSignInMethodsForEmail,
getAdditionalUserInfo: () => getAdditionalUserInfo,
getAuth: () => getAuth,
getIdToken: () => getIdToken,
getIdTokenResult: () => getIdTokenResult,
getMultiFactorResolver: () => getMultiFactorResolver,
getRedirectResult: () => getRedirectResult,
inMemoryPersistence: () => inMemoryPersistence,
indexedDBLocalPersistence: () => indexedDBLocalPersistence,
initializeAuth: () => initializeAuth,
initializeRecaptchaConfig: () => initializeRecaptchaConfig,
isSignInWithEmailLink: () => isSignInWithEmailLink,
linkWithCredential: () => linkWithCredential,
linkWithPhoneNumber: () => linkWithPhoneNumber,
linkWithPopup: () => linkWithPopup,
linkWithRedirect: () => linkWithRedirect,
multiFactor: () => multiFactor,
onAuthStateChanged: () => onAuthStateChanged,
onIdTokenChanged: () => onIdTokenChanged,
parseActionCodeURL: () => parseActionCodeURL,
prodErrorMap: () => prodErrorMap,
reauthenticateWithCredential: () => reauthenticateWithCredential,
reauthenticateWithPhoneNumber: () => reauthenticateWithPhoneNumber,
reauthenticateWithPopup: () => reauthenticateWithPopup,
reauthenticateWithRedirect: () => reauthenticateWithRedirect,
reload: () => reload,
revokeAccessToken: () => revokeAccessToken,
sendEmailVerification: () => sendEmailVerification,
sendPasswordResetEmail: () => sendPasswordResetEmail,
sendSignInLinkToEmail: () => sendSignInLinkToEmail,
setPersistence: () => setPersistence,
signInAnonymously: () => signInAnonymously,
signInWithCredential: () => signInWithCredential,
signInWithCustomToken: () => signInWithCustomToken,
signInWithEmailAndPassword: () => signInWithEmailAndPassword,
signInWithEmailLink: () => signInWithEmailLink,
signInWithPhoneNumber: () => signInWithPhoneNumber,
signInWithPopup: () => signInWithPopup,
signInWithRedirect: () => signInWithRedirect,
signOut: () => signOut,
unlink: () => unlink,
updateCurrentUser: () => updateCurrentUser,
updateEmail: () => updateEmail,
updatePassword: () => updatePassword,
updatePhoneNumber: () => updatePhoneNumber,
updateProfile: () => updateProfile,
useDeviceLanguage: () => useDeviceLanguage,
validatePassword: () => validatePassword,
verifyBeforeUpdateEmail: () => verifyBeforeUpdateEmail,
verifyPasswordResetCode: () => verifyPasswordResetCode
});
var init_dist2 = __esm({
"node_modules/firebase/auth/dist/index.mjs"() {
init_node_esm();
}
});
// node_modules/@firebase/functions/dist/esm/index.esm.js
function mapValues(o, f) {
const result = {};
for (const key in o) {
if (o.hasOwnProperty(key)) {
result[key] = f(o[key]);
}
}
return result;
}
function encode(data) {
if (data == null) {
return null;
}
if (data instanceof Number) {
data = data.valueOf();
}
if (typeof data === "number" && isFinite(data)) {
return data;
}
if (data === true || data === false) {
return data;
}
if (Object.prototype.toString.call(data) === "[object String]") {
return data;
}
if (data instanceof Date) {
return data.toISOString();
}
if (Array.isArray(data)) {
return data.map((x) => encode(x));
}
if (typeof data === "function" || typeof data === "object") {
return mapValues(data, (x) => encode(x));
}
throw new Error("Data cannot be encoded in JSON: " + data);
}
function decode(json) {
if (json == null) {
return json;
}
if (json["@type"]) {
switch (json["@type"]) {
case LONG_TYPE:
// Fall through and handle this the same as unsigned.
case UNSIGNED_LONG_TYPE: {
const value = Number(json["value"]);
if (isNaN(value)) {
throw new Error("Data cannot be decoded from JSON: " + json);
}
return value;
}
default: {
throw new Error("Data cannot be decoded from JSON: " + json);
}
}
}
if (Array.isArray(json)) {
return json.map((x) => decode(x));
}
if (typeof json === "function" || typeof json === "object") {
return mapValues(json, (x) => decode(x));
}
return json;
}
function codeForHTTPStatus(status) {
if (status >= 200 && status < 300) {
return "ok";
}
switch (status) {
case 0:
return "internal";
case 400:
return "invalid-argument";
case 401:
return "unauthenticated";
case 403:
return "permission-denied";
case 404:
return "not-found";
case 409:
return "aborted";
case 429:
return "resource-exhausted";
case 499:
return "cancelled";
case 500:
return "internal";
case 501:
return "unimplemented";
case 503:
return "unavailable";
case 504:
return "deadline-exceeded";
}
return "unknown";
}
function _errorForResponse(status, bodyJSON) {
let code = codeForHTTPStatus(status);
let description = code;
let details = void 0;
try {
const errorJSON = bodyJSON && bodyJSON.error;
if (errorJSON) {
const status2 = errorJSON.status;
if (typeof status2 === "string") {
if (!errorCodeMap[status2]) {
return new FunctionsError("internal", "internal");
}
code = errorCodeMap[status2];
description = status2;
}
const message = errorJSON.message;
if (typeof message === "string") {
description = message;
}
details = errorJSON.details;
if (details !== void 0) {
details = decode(details);
}
}
} catch (e) {
}
if (code === "ok") {
return null;
}
return new FunctionsError(code, description, details);
}
function failAfter(millis) {
let timer = null;
return {
promise: new Promise((_, reject) => {
timer = setTimeout(() => {
reject(new FunctionsError("deadline-exceeded", "deadline-exceeded"));
}, millis);
}),
cancel: () => {
if (timer) {
clearTimeout(timer);
}
}
};
}
function connectFunctionsEmulator$1(functionsInstance, host, port) {
const useSsl = isCloudWorkstation(host);
functionsInstance.emulatorOrigin = `http${useSsl ? "s" : ""}://${host}:${port}`;
if (useSsl) {
void pingServer(functionsInstance.emulatorOrigin + "/backends");
updateEmulatorBanner("Functions", true);
}
}
function httpsCallable$1(functionsInstance, name6, options) {
const callable = (data) => {
return call(functionsInstance, name6, data, options || {});
};
callable.stream = (data, options2) => {
return stream(functionsInstance, name6, data, options2);
};
return callable;
}
function httpsCallableFromURL$1(functionsInstance, url, options) {
const callable = (data) => {
return callAtURL(functionsInstance, url, data, options || {});
};
callable.stream = (data, options2) => {
return streamAtURL(functionsInstance, url, data, options2 || {});
};
return callable;
}
function getCredentials(functionsInstance) {
return functionsInstance.emulatorOrigin && isCloudWorkstation(functionsInstance.emulatorOrigin) ? "include" : void 0;
}
async function postJSON(url, body, headers, fetchImpl, functionsInstance) {
headers["Content-Type"] = "application/json";
let response;
try {
response = await fetchImpl(url, {
method: "POST",
body: JSON.stringify(body),
headers,
credentials: getCredentials(functionsInstance)
});
} catch (e) {
return {
status: 0,
json: null
};
}
let json = null;
try {
json = await response.json();
} catch (e) {
}
return {
status: response.status,
json
};
}
async function makeAuthHeaders(functionsInstance, options) {
const headers = {};
const context = await functionsInstance.contextProvider.getContext(options.limitedUseAppCheckTokens);
if (context.authToken) {
headers["Authorization"] = "Bearer " + context.authToken;
}
if (context.messagingToken) {
headers["Firebase-Instance-ID-Token"] = context.messagingToken;
}
if (context.appCheckToken !== null) {
headers["X-Firebase-AppCheck"] = context.appCheckToken;
}
return headers;
}
function call(functionsInstance, name6, data, options) {
const url = functionsInstance._url(name6);
return callAtURL(functionsInstance, url, data, options);
}
async function callAtURL(functionsInstance, url, data, options) {
data = encode(data);
const body = { data };
const headers = await makeAuthHeaders(functionsInstance, options);
const timeout = options.timeout || 7e4;
const failAfterHandle = failAfter(timeout);
const response = await Promise.race([
postJSON(url, body, headers, functionsInstance.fetchImpl, functionsInstance),
failAfterHandle.promise,
functionsInstance.cancelAllRequests
]);
failAfterHandle.cancel();
if (!response) {
throw new FunctionsError("cancelled", "Firebase Functions instance was deleted.");
}
const error = _errorForResponse(response.status, response.json);
if (error) {
throw error;
}
if (!response.json) {
throw new FunctionsError("internal", "Response is not valid JSON object.");
}
let responseData = response.json.data;
if (typeof responseData === "undefined") {
responseData = response.json.result;
}
if (typeof responseData === "undefined") {
throw new FunctionsError("internal", "Response is missing data field.");
}
const decodedData = decode(responseData);
return { data: decodedData };
}
function stream(functionsInstance, name6, data, options) {
const url = functionsInstance._url(name6);
return streamAtURL(functionsInstance, url, data, options || {});
}
async function streamAtURL(functionsInstance, url, data, options) {
data = encode(data);
const body = { data };
const headers = await makeAuthHeaders(functionsInstance, options);
headers["Content-Type"] = "application/json";
headers["Accept"] = "text/event-stream";
let response;
try {
response = await functionsInstance.fetchImpl(url, {
method: "POST",
body: JSON.stringify(body),
headers,
signal: options?.signal,
credentials: getCredentials(functionsInstance)
});
} catch (e) {
if (e instanceof Error && e.name === "AbortError") {
const error2 = new FunctionsError("cancelled", "Request was cancelled.");
return {
data: Promise.reject(error2),
stream: {
[Symbol.asyncIterator]() {
return {
next() {
return Promise.reject(error2);
}
};
}
}
};
}
const error = _errorForResponse(0, null);
return {
data: Promise.reject(error),
// Return an empty async iterator
stream: {
[Symbol.asyncIterator]() {
return {
next() {
return Promise.reject(error);
}
};
}
}
};
}
let resultResolver;
let resultRejecter;
const resultPromise = new Promise((resolve, reject) => {
resultResolver = resolve;
resultRejecter = reject;
});
options?.signal?.addEventListener("abort", () => {
const error = new FunctionsError("cancelled", "Request was cancelled.");
resultRejecter(error);
});
const reader = response.body.getReader();
const rstream = createResponseStream(reader, resultResolver, resultRejecter, options?.signal);
return {
stream: {
[Symbol.asyncIterator]() {
const rreader = rstream.getReader();
return {
async next() {
const { value, done } = await rreader.read();
return { value, done };
},
async return() {
await rreader.cancel();
return { done: true, value: void 0 };
}
};
}
},
data: resultPromise
};
}
function createResponseStream(reader, resultResolver, resultRejecter, signal) {
const processLine = (line, controller) => {
const match = line.match(responseLineRE);
if (!match) {
return;
}
const data = match[1];
try {
const jsonData = JSON.parse(data);
if ("result" in jsonData) {
resultResolver(decode(jsonData.result));
return;
}
if ("message" in jsonData) {
controller.enqueue(decode(jsonData.message));
return;
}
if ("error" in jsonData) {
const error = _errorForResponse(0, jsonData);
controller.error(error);
resultRejecter(error);
return;
}
} catch (error) {
if (error instanceof FunctionsError) {
controller.error(error);
resultRejecter(error);
return;
}
}
};
const decoder = new TextDecoder();
return new ReadableStream({
start(controller) {
let currentText = "";
return pump();
async function pump() {
if (signal?.aborted) {
const error = new FunctionsError("cancelled", "Request was cancelled");
controller.error(error);
resultRejecter(error);
return Promise.resolve();
}
try {
const { value, done } = await reader.read();
if (done) {
if (currentText.trim()) {
processLine(currentText.trim(), controller);
}
controller.close();
return;
}
if (signal?.aborted) {
const error = new FunctionsError("cancelled", "Request was cancelled");
controller.error(error);
resultRejecter(error);
await reader.cancel();
return;
}
currentText += decoder.decode(value, { stream: true });
const lines = currentText.split("\n");
currentText = lines.pop() || "";
for (const line of lines) {
if (line.trim()) {
processLine(line.trim(), controller);
}
}
return pump();
} catch (error) {
const functionsError = error instanceof FunctionsError ? error : _errorForResponse(0, null);
controller.error(functionsError);
resultRejecter(functionsError);
}
}
},
cancel() {
return reader.cancel();
}
});
}
function registerFunctions(variant) {
const factory2 = (container, { instanceIdentifier: regionOrCustomDomain }) => {
const app2 = container.getProvider("app").getImmediate();
const authProvider = container.getProvider(AUTH_INTERNAL_NAME);
const messagingProvider = container.getProvider(MESSAGING_INTERNAL_NAME);
const appCheckProvider = container.getProvider(APP_CHECK_INTERNAL_NAME);
return new FunctionsService(app2, authProvider, messagingProvider, appCheckProvider, regionOrCustomDomain);
};
_registerComponent(new Component(
FUNCTIONS_TYPE,
factory2,
"PUBLIC"
/* ComponentType.PUBLIC */
).setMultipleInstances(true));
registerVersion(name4, version4, variant);
registerVersion(name4, version4, "esm2020");
}
function getFunctions(app2 = getApp(), regionOrCustomDomain = DEFAULT_REGION) {
const functionsProvider = _getProvider(getModularInstance(app2), FUNCTIONS_TYPE);
const functionsInstance = functionsProvider.getImmediate({
identifier: regionOrCustomDomain
});
const emulator = getDefaultEmulatorHostnameAndPort("functions");
if (emulator) {
connectFunctionsEmulator(functionsInstance, ...emulator);
}
return functionsInstance;
}
function connectFunctionsEmulator(functionsInstance, host, port) {
connectFunctionsEmulator$1(getModularInstance(functionsInstance), host, port);
}
function httpsCallable(functionsInstance, name6, options) {
return httpsCallable$1(getModularInstance(functionsInstance), name6, options);
}
function httpsCallableFromURL(functionsInstance, url, options) {
return httpsCallableFromURL$1(getModularInstance(functionsInstance), url, options);
}
var LONG_TYPE, UNSIGNED_LONG_TYPE, FUNCTIONS_TYPE, errorCodeMap, FunctionsError, ContextProvider, DEFAULT_REGION, responseLineRE, FunctionsService, name4, version4, AUTH_INTERNAL_NAME, APP_CHECK_INTERNAL_NAME, MESSAGING_INTERNAL_NAME;
var init_index_esm4 = __esm({
"node_modules/@firebase/functions/dist/esm/index.esm.js"() {
init_index_esm3();
init_index_node_esm();
init_index_esm();
LONG_TYPE = "type.googleapis.com/google.protobuf.Int64Value";
UNSIGNED_LONG_TYPE = "type.googleapis.com/google.protobuf.UInt64Value";
FUNCTIONS_TYPE = "functions";
errorCodeMap = {
OK: "ok",
CANCELLED: "cancelled",
UNKNOWN: "unknown",
INVALID_ARGUMENT: "invalid-argument",
DEADLINE_EXCEEDED: "deadline-exceeded",
NOT_FOUND: "not-found",
ALREADY_EXISTS: "already-exists",
PERMISSION_DENIED: "permission-denied",
UNAUTHENTICATED: "unauthenticated",
RESOURCE_EXHAUSTED: "resource-exhausted",
FAILED_PRECONDITION: "failed-precondition",
ABORTED: "aborted",
OUT_OF_RANGE: "out-of-range",
UNIMPLEMENTED: "unimplemented",
INTERNAL: "internal",
UNAVAILABLE: "unavailable",
DATA_LOSS: "data-loss"
};
FunctionsError = class _FunctionsError extends FirebaseError {
/**
* Constructs a new instance of the `FunctionsError` class.
*/
constructor(code, message, details) {
super(`${FUNCTIONS_TYPE}/${code}`, message || "");
this.details = details;
Object.setPrototypeOf(this, _FunctionsError.prototype);
}
};
ContextProvider = class {
constructor(app2, authProvider, messagingProvider, appCheckProvider) {
this.app = app2;
this.auth = null;
this.messaging = null;
this.appCheck = null;
this.serverAppAppCheckToken = null;
if (_isFirebaseServerApp(app2) && app2.settings.appCheckToken) {
this.serverAppAppCheckToken = app2.settings.appCheckToken;
}
this.auth = authProvider.getImmediate({ optional: true });
this.messaging = messagingProvider.getImmediate({
optional: true
});
if (!this.auth) {
authProvider.get().then((auth2) => this.auth = auth2, () => {
});
}
if (!this.messaging) {
messagingProvider.get().then((messaging) => this.messaging = messaging, () => {
});
}
if (!this.appCheck) {
appCheckProvider?.get().then((appCheck) => this.appCheck = appCheck, () => {
});
}
}
async getAuthToken() {
if (!this.auth) {
return void 0;
}
try {
const token = await this.auth.getToken();
return token?.accessToken;
} catch (e) {
return void 0;
}
}
async getMessagingToken() {
if (!this.messaging || !("Notification" in self) || Notification.permission !== "granted") {
return void 0;
}
try {
return await this.messaging.getToken();
} catch (e) {
return void 0;
}
}
async getAppCheckToken(limitedUseAppCheckTokens) {
if (this.serverAppAppCheckToken) {
return this.serverAppAppCheckToken;
}
if (this.appCheck) {
const result = limitedUseAppCheckTokens ? await this.appCheck.getLimitedUseToken() : await this.appCheck.getToken();
if (result.error) {
return null;
}
return result.token;
}
return null;
}
async getContext(limitedUseAppCheckTokens) {
const authToken = await this.getAuthToken();
const messagingToken = await this.getMessagingToken();
const appCheckToken = await this.getAppCheckToken(limitedUseAppCheckTokens);
return { authToken, messagingToken, appCheckToken };
}
};
DEFAULT_REGION = "us-central1";
responseLineRE = /^data: (.*?)(?:\n|$)/;
FunctionsService = class {
/**
* Creates a new Functions service for the given app.
* @param app - The FirebaseApp to use.
*/
constructor(app2, authProvider, messagingProvider, appCheckProvider, regionOrCustomDomain = DEFAULT_REGION, fetchImpl = (...args) => fetch(...args)) {
this.app = app2;
this.fetchImpl = fetchImpl;
this.emulatorOrigin = null;
this.contextProvider = new ContextProvider(app2, authProvider, messagingProvider, appCheckProvider);
this.cancelAllRequests = new Promise((resolve) => {
this.deleteService = () => {
return Promise.resolve(resolve());
};
});
try {
const url = new URL(regionOrCustomDomain);
this.customDomain = url.origin + (url.pathname === "/" ? "" : url.pathname);
this.region = DEFAULT_REGION;
} catch (e) {
this.customDomain = null;
this.region = regionOrCustomDomain;
}
}
_delete() {
return this.deleteService();
}
/**
* Returns the URL for a callable with the given name.
* @param name - The name of the callable.
* @internal
*/
_url(name6) {
const projectId = this.app.options.projectId;
if (this.emulatorOrigin !== null) {
const origin = this.emulatorOrigin;
return `${origin}/${projectId}/${this.region}/${name6}`;
}
if (this.customDomain !== null) {
return `${this.customDomain}/${name6}`;
}
return `https://${this.region}-${projectId}.cloudfunctions.net/${name6}`;
}
};
name4 = "@firebase/functions";
version4 = "0.13.1";
AUTH_INTERNAL_NAME = "auth-internal";
APP_CHECK_INTERNAL_NAME = "app-check-internal";
MESSAGING_INTERNAL_NAME = "messaging-internal";
registerFunctions();
}
});
// node_modules/firebase/functions/dist/index.mjs
var dist_exports2 = {};
__export(dist_exports2, {
FunctionsError: () => FunctionsError,
connectFunctionsEmulator: () => connectFunctionsEmulator,
getFunctions: () => getFunctions,
httpsCallable: () => httpsCallable,
httpsCallableFromURL: () => httpsCallableFromURL
});
var init_dist3 = __esm({
"node_modules/firebase/functions/dist/index.mjs"() {
init_index_esm4();
}
});
// node_modules/@firebase/storage/dist/node-esm/index.node.esm.js
function prependCode(code) {
return "storage/" + code;
}
function unknown() {
const message = "An unknown error occurred, please check the error payload for server response.";
return new StorageError(StorageErrorCode.UNKNOWN, message);
}
function objectNotFound(path) {
return new StorageError(StorageErrorCode.OBJECT_NOT_FOUND, "Object '" + path + "' does not exist.");
}
function quotaExceeded(bucket) {
return new StorageError(StorageErrorCode.QUOTA_EXCEEDED, "Quota for bucket '" + bucket + "' exceeded, please view quota on https://firebase.google.com/pricing/.");
}
function unauthenticated() {
const message = "User is not authenticated, please authenticate using Firebase Authentication and try again.";
return new StorageError(StorageErrorCode.UNAUTHENTICATED, message);
}
function unauthorizedApp() {
return new StorageError(StorageErrorCode.UNAUTHORIZED_APP, "This app does not have permission to access Firebase Storage on this project.");
}
function unauthorized(path) {
return new StorageError(StorageErrorCode.UNAUTHORIZED, "User does not have permission to access '" + path + "'.");
}
function retryLimitExceeded() {
return new StorageError(StorageErrorCode.RETRY_LIMIT_EXCEEDED, "Max retry time for operation exceeded, please try again.");
}
function canceled() {
return new StorageError(StorageErrorCode.CANCELED, "User canceled the upload/download.");
}
function invalidUrl(url) {
return new StorageError(StorageErrorCode.INVALID_URL, "Invalid URL '" + url + "'.");
}
function invalidDefaultBucket(bucket) {
return new StorageError(StorageErrorCode.INVALID_DEFAULT_BUCKET, "Invalid default bucket '" + bucket + "'.");
}
function noDefaultBucket() {
return new StorageError(StorageErrorCode.NO_DEFAULT_BUCKET, "No default bucket found. Did you set the '" + CONFIG_STORAGE_BUCKET_KEY + "' property when initializing the app?");
}
function cannotSliceBlob() {
return new StorageError(StorageErrorCode.CANNOT_SLICE_BLOB, "Cannot slice blob for upload. Please retry the upload.");
}
function noDownloadURL() {
return new StorageError(StorageErrorCode.NO_DOWNLOAD_URL, "The given file does not have any download URLs.");
}
function invalidArgument(message) {
return new StorageError(StorageErrorCode.INVALID_ARGUMENT, message);
}
function appDeleted() {
return new StorageError(StorageErrorCode.APP_DELETED, "The Firebase app was deleted.");
}
function invalidRootOperation(name6) {
return new StorageError(StorageErrorCode.INVALID_ROOT_OPERATION, "The operation '" + name6 + "' cannot be performed on a root reference, create a non-root reference using child, such as .child('file.png').");
}
function invalidFormat(format, message) {
return new StorageError(StorageErrorCode.INVALID_FORMAT, "String does not match format '" + format + "': " + message);
}
function internalError(message) {
throw new StorageError(StorageErrorCode.INTERNAL_ERROR, "Internal error: " + message);
}
function start(doRequest, backoffCompleteCb, timeout) {
let waitSeconds = 1;
let retryTimeoutId = null;
let globalTimeoutId = null;
let hitTimeout = false;
let cancelState = 0;
function canceled2() {
return cancelState === 2;
}
let triggeredCallback = false;
function triggerCallback(...args) {
if (!triggeredCallback) {
triggeredCallback = true;
backoffCompleteCb.apply(null, args);
}
}
function callWithDelay(millis) {
retryTimeoutId = setTimeout(() => {
retryTimeoutId = null;
doRequest(responseHandler, canceled2());
}, millis);
}
function clearGlobalTimeout() {
if (globalTimeoutId) {
clearTimeout(globalTimeoutId);
}
}
function responseHandler(success, ...args) {
if (triggeredCallback) {
clearGlobalTimeout();
return;
}
if (success) {
clearGlobalTimeout();
triggerCallback.call(null, success, ...args);
return;
}
const mustStop = canceled2() || hitTimeout;
if (mustStop) {
clearGlobalTimeout();
triggerCallback.call(null, success, ...args);
return;
}
if (waitSeconds < 64) {
waitSeconds *= 2;
}
let waitMillis;
if (cancelState === 1) {
cancelState = 2;
waitMillis = 0;
} else {
waitMillis = (waitSeconds + Math.random()) * 1e3;
}
callWithDelay(waitMillis);
}
let stopped = false;
function stop2(wasTimeout) {
if (stopped) {
return;
}
stopped = true;
clearGlobalTimeout();
if (triggeredCallback) {
return;
}
if (retryTimeoutId !== null) {
if (!wasTimeout) {
cancelState = 2;
}
clearTimeout(retryTimeoutId);
callWithDelay(0);
} else {
if (!wasTimeout) {
cancelState = 1;
}
}
}
callWithDelay(0);
globalTimeoutId = setTimeout(() => {
hitTimeout = true;
stop2(true);
}, timeout);
return stop2;
}
function stop(id) {
id(false);
}
function isJustDef(p) {
return p !== void 0;
}
function isNonArrayObject(p) {
return typeof p === "object" && !Array.isArray(p);
}
function isString(p) {
return typeof p === "string" || p instanceof String;
}
function isNativeBlob(p) {
return isNativeBlobDefined() && p instanceof Blob;
}
function isNativeBlobDefined() {
return typeof Blob !== "undefined";
}
function validateNumber(argument, minValue, maxValue, value) {
if (value < minValue) {
throw invalidArgument(`Invalid value for '${argument}'. Expected ${minValue} or greater.`);
}
if (value > maxValue) {
throw invalidArgument(`Invalid value for '${argument}'. Expected ${maxValue} or less.`);
}
}
function makeUrl(urlPart, host, protocol) {
let origin = host;
if (protocol == null) {
origin = `https://${host}`;
}
return `${protocol}://${origin}/v0${urlPart}`;
}
function makeQueryString(params) {
const encode2 = encodeURIComponent;
let queryPart = "?";
for (const key in params) {
if (params.hasOwnProperty(key)) {
const nextPart = encode2(key) + "=" + encode2(params[key]);
queryPart = queryPart + nextPart + "&";
}
}
queryPart = queryPart.slice(0, -1);
return queryPart;
}
function isRetryStatusCode(status, additionalRetryCodes) {
const isFiveHundredCode = status >= 500 && status < 600;
const extraRetryCodes = [
// Request Timeout: web server didn't receive full request in time.
408,
// Too Many Requests: you're getting rate-limited, basically.
429
];
const isExtraRetryCode = extraRetryCodes.indexOf(status) !== -1;
const isAdditionalRetryCode = additionalRetryCodes.indexOf(status) !== -1;
return isFiveHundredCode || isExtraRetryCode || isAdditionalRetryCode;
}
function addAuthHeader_(headers, authToken) {
if (authToken !== null && authToken.length > 0) {
headers["Authorization"] = "Firebase " + authToken;
}
}
function addVersionHeader_(headers, firebaseVersion) {
headers["X-Firebase-Storage-Version"] = "webjs/" + (firebaseVersion ?? "AppManager");
}
function addGmpidHeader_(headers, appId) {
if (appId) {
headers["X-Firebase-GMPID"] = appId;
}
}
function addAppCheckHeader_(headers, appCheckToken) {
if (appCheckToken !== null) {
headers["X-Firebase-AppCheck"] = appCheckToken;
}
}
function makeRequest(requestInfo, appId, authToken, appCheckToken, requestFactory, firebaseVersion, retry = true, isUsingEmulator = false) {
const queryPart = makeQueryString(requestInfo.urlParams);
const url = requestInfo.url + queryPart;
const headers = Object.assign({}, requestInfo.headers);
addGmpidHeader_(headers, appId);
addAuthHeader_(headers, authToken);
addVersionHeader_(headers, firebaseVersion);
addAppCheckHeader_(headers, appCheckToken);
return new NetworkRequest(url, requestInfo.method, headers, requestInfo.body, requestInfo.successCodes, requestInfo.additionalRetryCodes, requestInfo.handler, requestInfo.errorHandler, requestInfo.timeout, requestInfo.progressCallback, requestFactory, retry, isUsingEmulator);
}
function getBlobBuilder() {
if (typeof BlobBuilder !== "undefined") {
return BlobBuilder;
} else if (typeof WebKitBlobBuilder !== "undefined") {
return WebKitBlobBuilder;
} else {
return void 0;
}
}
function getBlob$1(...args) {
const BlobBuilder2 = getBlobBuilder();
if (BlobBuilder2 !== void 0) {
const bb = new BlobBuilder2();
for (let i = 0; i < args.length; i++) {
bb.append(args[i]);
}
return bb.getBlob();
} else {
if (isNativeBlobDefined()) {
return new Blob(args);
} else {
throw new StorageError(StorageErrorCode.UNSUPPORTED_ENVIRONMENT, "This browser doesn't seem to support creating Blobs");
}
}
}
function sliceBlob(blob, start2, end) {
if (blob.webkitSlice) {
return blob.webkitSlice(start2, end);
} else if (blob.mozSlice) {
return blob.mozSlice(start2, end);
} else if (blob.slice) {
return blob.slice(start2, end);
}
return null;
}
function decodeBase64(encoded) {
if (/[^-A-Za-z0-9+/=]/.test(encoded)) {
throw invalidFormat("base64", "Invalid character found");
}
return Buffer.from(encoded, "base64").toString("binary");
}
function dataFromString(format, stringData) {
switch (format) {
case StringFormat.RAW:
return new StringData(utf8Bytes_(stringData));
case StringFormat.BASE64:
case StringFormat.BASE64URL:
return new StringData(base64Bytes_(format, stringData));
case StringFormat.DATA_URL:
return new StringData(dataURLBytes_(stringData), dataURLContentType_(stringData));
}
throw unknown();
}
function utf8Bytes_(value) {
const b = [];
for (let i = 0; i < value.length; i++) {
let c = value.charCodeAt(i);
if (c <= 127) {
b.push(c);
} else {
if (c <= 2047) {
b.push(192 | c >> 6, 128 | c & 63);
} else {
if ((c & 64512) === 55296) {
const valid = i < value.length - 1 && (value.charCodeAt(i + 1) & 64512) === 56320;
if (!valid) {
b.push(239, 191, 189);
} else {
const hi = c;
const lo = value.charCodeAt(++i);
c = 65536 | (hi & 1023) << 10 | lo & 1023;
b.push(240 | c >> 18, 128 | c >> 12 & 63, 128 | c >> 6 & 63, 128 | c & 63);
}
} else {
if ((c & 64512) === 56320) {
b.push(239, 191, 189);
} else {
b.push(224 | c >> 12, 128 | c >> 6 & 63, 128 | c & 63);
}
}
}
}
}
return new Uint8Array(b);
}
function percentEncodedBytes_(value) {
let decoded;
try {
decoded = decodeURIComponent(value);
} catch (e) {
throw invalidFormat(StringFormat.DATA_URL, "Malformed data URL.");
}
return utf8Bytes_(decoded);
}
function base64Bytes_(format, value) {
switch (format) {
case StringFormat.BASE64: {
const hasMinus = value.indexOf("-") !== -1;
const hasUnder = value.indexOf("_") !== -1;
if (hasMinus || hasUnder) {
const invalidChar = hasMinus ? "-" : "_";
throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64url encoded?");
}
break;
}
case StringFormat.BASE64URL: {
const hasPlus = value.indexOf("+") !== -1;
const hasSlash = value.indexOf("/") !== -1;
if (hasPlus || hasSlash) {
const invalidChar = hasPlus ? "+" : "/";
throw invalidFormat(format, "Invalid character '" + invalidChar + "' found: is it base64 encoded?");
}
value = value.replace(/-/g, "+").replace(/_/g, "/");
break;
}
}
let bytes;
try {
bytes = decodeBase64(value);
} catch (e) {
if (e.message.includes("polyfill")) {
throw e;
}
throw invalidFormat(format, "Invalid character found");
}
const array = new Uint8Array(bytes.length);
for (let i = 0; i < bytes.length; i++) {
array[i] = bytes.charCodeAt(i);
}
return array;
}
function dataURLBytes_(dataUrl) {
const parts = new DataURLParts(dataUrl);
if (parts.base64) {
return base64Bytes_(StringFormat.BASE64, parts.rest);
} else {
return percentEncodedBytes_(parts.rest);
}
}
function dataURLContentType_(dataUrl) {
const parts = new DataURLParts(dataUrl);
return parts.contentType;
}
function endsWith(s, end) {
const longEnough = s.length >= end.length;
if (!longEnough) {
return false;
}
return s.substring(s.length - end.length) === end;
}
function jsonObjectOrNull(s) {
let obj;
try {
obj = JSON.parse(s);
} catch (e) {
return null;
}
if (isNonArrayObject(obj)) {
return obj;
} else {
return null;
}
}
function parent(path) {
if (path.length === 0) {
return null;
}
const index = path.lastIndexOf("/");
if (index === -1) {
return "";
}
const newPath = path.slice(0, index);
return newPath;
}
function child(path, childPath) {
const canonicalChildPath = childPath.split("/").filter((component) => component.length > 0).join("/");
if (path.length === 0) {
return canonicalChildPath;
} else {
return path + "/" + canonicalChildPath;
}
}
function lastComponent(path) {
const index = path.lastIndexOf("/", path.length - 2);
if (index === -1) {
return path;
} else {
return path.slice(index + 1);
}
}
function noXform_(metadata, value) {
return value;
}
function xformPath(fullPath) {
if (!isString(fullPath) || fullPath.length < 2) {
return fullPath;
} else {
return lastComponent(fullPath);
}
}
function getMappings() {
if (mappings_) {
return mappings_;
}
const mappings = [];
mappings.push(new Mapping("bucket"));
mappings.push(new Mapping("generation"));
mappings.push(new Mapping("metageneration"));
mappings.push(new Mapping("name", "fullPath", true));
function mappingsXformPath(_metadata, fullPath) {
return xformPath(fullPath);
}
const nameMapping = new Mapping("name");
nameMapping.xform = mappingsXformPath;
mappings.push(nameMapping);
function xformSize(_metadata, size) {
if (size !== void 0) {
return Number(size);
} else {
return size;
}
}
const sizeMapping = new Mapping("size");
sizeMapping.xform = xformSize;
mappings.push(sizeMapping);
mappings.push(new Mapping("timeCreated"));
mappings.push(new Mapping("updated"));
mappings.push(new Mapping("md5Hash", null, true));
mappings.push(new Mapping("cacheControl", null, true));
mappings.push(new Mapping("contentDisposition", null, true));
mappings.push(new Mapping("contentEncoding", null, true));
mappings.push(new Mapping("contentLanguage", null, true));
mappings.push(new Mapping("contentType", null, true));
mappings.push(new Mapping("metadata", "customMetadata", true));
mappings_ = mappings;
return mappings_;
}
function addRef(metadata, service) {
function generateRef() {
const bucket = metadata["bucket"];
const path = metadata["fullPath"];
const loc = new Location(bucket, path);
return service._makeStorageReference(loc);
}
Object.defineProperty(metadata, "ref", { get: generateRef });
}
function fromResource(service, resource, mappings) {
const metadata = {};
metadata["type"] = "file";
const len = mappings.length;
for (let i = 0; i < len; i++) {
const mapping = mappings[i];
metadata[mapping.local] = mapping.xform(metadata, resource[mapping.server]);
}
addRef(metadata, service);
return metadata;
}
function fromResourceString(service, resourceString, mappings) {
const obj = jsonObjectOrNull(resourceString);
if (obj === null) {
return null;
}
const resource = obj;
return fromResource(service, resource, mappings);
}
function downloadUrlFromResourceString(metadata, resourceString, host, protocol) {
const obj = jsonObjectOrNull(resourceString);
if (obj === null) {
return null;
}
if (!isString(obj["downloadTokens"])) {
return null;
}
const tokens = obj["downloadTokens"];
if (tokens.length === 0) {
return null;
}
const encode2 = encodeURIComponent;
const tokensList = tokens.split(",");
const urls = tokensList.map((token) => {
const bucket = metadata["bucket"];
const path = metadata["fullPath"];
const urlPart = "/b/" + encode2(bucket) + "/o/" + encode2(path);
const base = makeUrl(urlPart, host, protocol);
const queryString = makeQueryString({
alt: "media",
token
});
return base + queryString;
});
return urls[0];
}
function toResourceString(metadata, mappings) {
const resource = {};
const len = mappings.length;
for (let i = 0; i < len; i++) {
const mapping = mappings[i];
if (mapping.writable) {
resource[mapping.server] = metadata[mapping.local];
}
}
return JSON.stringify(resource);
}
function handlerCheck(cndn) {
if (!cndn) {
throw unknown();
}
}
function metadataHandler(service, mappings) {
function handler(xhr, text) {
const metadata = fromResourceString(service, text, mappings);
handlerCheck(metadata !== null);
return metadata;
}
return handler;
}
function downloadUrlHandler(service, mappings) {
function handler(xhr, text) {
const metadata = fromResourceString(service, text, mappings);
handlerCheck(metadata !== null);
return downloadUrlFromResourceString(metadata, text, service.host, service._protocol);
}
return handler;
}
function sharedErrorHandler(location) {
function errorHandler(xhr, err) {
let newErr;
if (xhr.getStatus() === 401) {
if (
// This exact message string is the only consistent part of the
// server's error response that identifies it as an App Check error.
xhr.getErrorText().includes("Firebase App Check token is invalid")
) {
newErr = unauthorizedApp();
} else {
newErr = unauthenticated();
}
} else {
if (xhr.getStatus() === 402) {
newErr = quotaExceeded(location.bucket);
} else {
if (xhr.getStatus() === 403) {
newErr = unauthorized(location.path);
} else {
newErr = err;
}
}
}
newErr.status = xhr.getStatus();
newErr.serverResponse = err.serverResponse;
return newErr;
}
return errorHandler;
}
function objectErrorHandler(location) {
const shared = sharedErrorHandler(location);
function errorHandler(xhr, err) {
let newErr = shared(xhr, err);
if (xhr.getStatus() === 404) {
newErr = objectNotFound(location.path);
}
newErr.serverResponse = err.serverResponse;
return newErr;
}
return errorHandler;
}
function getDownloadUrl(service, location, mappings) {
const urlPart = location.fullServerUrl();
const url = makeUrl(urlPart, service.host, service._protocol);
const method = "GET";
const timeout = service.maxOperationRetryTime;
const requestInfo = new RequestInfo(url, method, downloadUrlHandler(service, mappings), timeout);
requestInfo.errorHandler = objectErrorHandler(location);
return requestInfo;
}
function determineContentType_(metadata, blob) {
return metadata && metadata["contentType"] || blob && blob.type() || "application/octet-stream";
}
function metadataForUpload_(location, blob, metadata) {
const metadataClone = Object.assign({}, metadata);
metadataClone["fullPath"] = location.path;
metadataClone["size"] = blob.size();
if (!metadataClone["contentType"]) {
metadataClone["contentType"] = determineContentType_(null, blob);
}
return metadataClone;
}
function multipartUpload(service, location, mappings, blob, metadata) {
const urlPart = location.bucketOnlyServerUrl();
const headers = {
"X-Goog-Upload-Protocol": "multipart"
};
function genBoundary() {
let str = "";
for (let i = 0; i < 2; i++) {
str = str + Math.random().toString().slice(2);
}
return str;
}
const boundary = genBoundary();
headers["Content-Type"] = "multipart/related; boundary=" + boundary;
const metadata_ = metadataForUpload_(location, blob, metadata);
const metadataString = toResourceString(metadata_, mappings);
const preBlobPart = "--" + boundary + "\r\nContent-Type: application/json; charset=utf-8\r\n\r\n" + metadataString + "\r\n--" + boundary + "\r\nContent-Type: " + metadata_["contentType"] + "\r\n\r\n";
const postBlobPart = "\r\n--" + boundary + "--";
const body = FbsBlob.getBlob(preBlobPart, blob, postBlobPart);
if (body === null) {
throw cannotSliceBlob();
}
const urlParams = { name: metadata_["fullPath"] };
const url = makeUrl(urlPart, service.host, service._protocol);
const method = "POST";
const timeout = service.maxUploadRetryTime;
const requestInfo = new RequestInfo(url, method, metadataHandler(service, mappings), timeout);
requestInfo.urlParams = urlParams;
requestInfo.headers = headers;
requestInfo.body = body.uploadData();
requestInfo.errorHandler = sharedErrorHandler(location);
return requestInfo;
}
function newTextConnection() {
return textFactoryOverride ? textFactoryOverride() : new FetchTextConnection();
}
function newFetch(url, method, isUsingEmulator, headers, body) {
const fetchArgs = {
method,
headers: headers || {},
body
};
if (isCloudWorkstation(url) && isUsingEmulator) {
fetchArgs.credentials = "include";
}
return fetch(url, fetchArgs);
}
function uploadBytes$1(ref2, data, metadata) {
ref2._throwIfRoot("uploadBytes");
const requestInfo = multipartUpload(ref2.storage, ref2._location, getMappings(), new FbsBlob(data, true), metadata);
return ref2.storage.makeRequestWithTokens(requestInfo, newTextConnection).then((finalMetadata) => {
return {
metadata: finalMetadata,
ref: ref2
};
});
}
function getDownloadURL$1(ref2) {
ref2._throwIfRoot("getDownloadURL");
const requestInfo = getDownloadUrl(ref2.storage, ref2._location, getMappings());
return ref2.storage.makeRequestWithTokens(requestInfo, newTextConnection).then((url) => {
if (url === null) {
throw noDownloadURL();
}
return url;
});
}
function _getChild$1(ref2, childPath) {
const newPath = child(ref2._location.path, childPath);
const location = new Location(ref2._location.bucket, newPath);
return new Reference(ref2.storage, location);
}
function isUrl(path) {
return /^[A-Za-z]+:\/\//.test(path);
}
function refFromURL(service, url) {
return new Reference(service, url);
}
function refFromPath(ref2, path) {
if (ref2 instanceof FirebaseStorageImpl) {
const service = ref2;
if (service._bucket == null) {
throw noDefaultBucket();
}
const reference = new Reference(service, service._bucket);
if (path != null) {
return refFromPath(reference, path);
} else {
return reference;
}
} else {
if (path !== void 0) {
return _getChild$1(ref2, path);
} else {
return ref2;
}
}
}
function ref$1(serviceOrRef, pathOrUrl) {
if (pathOrUrl && isUrl(pathOrUrl)) {
if (serviceOrRef instanceof FirebaseStorageImpl) {
return refFromURL(serviceOrRef, pathOrUrl);
} else {
throw invalidArgument("To use ref(service, url), the first argument must be a Storage instance.");
}
} else {
return refFromPath(serviceOrRef, pathOrUrl);
}
}
function extractBucket(host, config) {
const bucketString = config?.[CONFIG_STORAGE_BUCKET_KEY];
if (bucketString == null) {
return null;
}
return Location.makeFromBucketSpec(bucketString, host);
}
function connectStorageEmulator$1(storage2, host, port, options = {}) {
storage2.host = `${host}:${port}`;
const useSsl = isCloudWorkstation(host);
if (useSsl) {
void pingServer(`https://${storage2.host}/b`);
updateEmulatorBanner("Storage", true);
}
storage2._isUsingEmulator = true;
storage2._protocol = useSsl ? "https" : "http";
const { mockUserToken } = options;
if (mockUserToken) {
storage2._overrideAuthToken = typeof mockUserToken === "string" ? mockUserToken : createMockUserToken(mockUserToken, storage2.app.options.projectId);
}
}
function uploadBytes(ref2, data, metadata) {
ref2 = getModularInstance(ref2);
return uploadBytes$1(ref2, data, metadata);
}
function getDownloadURL(ref2) {
ref2 = getModularInstance(ref2);
return getDownloadURL$1(ref2);
}
function ref(serviceOrRef, pathOrUrl) {
serviceOrRef = getModularInstance(serviceOrRef);
return ref$1(serviceOrRef, pathOrUrl);
}
function getStorage(app2 = getApp(), bucketUrl) {
app2 = getModularInstance(app2);
const storageProvider = _getProvider(app2, STORAGE_TYPE);
const storageInstance = storageProvider.getImmediate({
identifier: bucketUrl
});
const emulator = getDefaultEmulatorHostnameAndPort("storage");
if (emulator) {
connectStorageEmulator(storageInstance, ...emulator);
}
return storageInstance;
}
function connectStorageEmulator(storage2, host, port, options = {}) {
connectStorageEmulator$1(storage2, host, port, options);
}
function factory(container, { instanceIdentifier: url }) {
const app2 = container.getProvider("app").getImmediate();
const authProvider = container.getProvider("auth-internal");
const appCheckProvider = container.getProvider("app-check-internal");
return new FirebaseStorageImpl(app2, authProvider, appCheckProvider, url, SDK_VERSION);
}
function registerStorage() {
_registerComponent(new Component(
STORAGE_TYPE,
factory,
"PUBLIC"
/* ComponentType.PUBLIC */
).setMultipleInstances(true));
registerVersion(name5, version5);
}
var DEFAULT_HOST, CONFIG_STORAGE_BUCKET_KEY, DEFAULT_MAX_OPERATION_RETRY_TIME, DEFAULT_MAX_UPLOAD_RETRY_TIME, StorageError, StorageErrorCode, Location, FailRequest, ErrorCode, NetworkRequest, RequestEndStatus, StringFormat, StringData, DataURLParts, FbsBlob, Mapping, mappings_, RequestInfo, RESUMABLE_UPLOAD_CHUNK_SIZE, textFactoryOverride, FetchConnection, FetchTextConnection, Reference, FirebaseStorageImpl, name5, version5, STORAGE_TYPE;
var init_index_node_esm2 = __esm({
"node_modules/@firebase/storage/dist/node-esm/index.node.esm.js"() {
init_index_esm3();
init_index_node_esm();
init_index_esm();
DEFAULT_HOST = "firebasestorage.googleapis.com";
CONFIG_STORAGE_BUCKET_KEY = "storageBucket";
DEFAULT_MAX_OPERATION_RETRY_TIME = 2 * 60 * 1e3;
DEFAULT_MAX_UPLOAD_RETRY_TIME = 10 * 60 * 1e3;
StorageError = class _StorageError extends FirebaseError {
/**
* @param code - A `StorageErrorCode` string to be prefixed with 'storage/' and
* added to the end of the message.
* @param message - Error message.
* @param status_ - Corresponding HTTP Status Code
*/
constructor(code, message, status_ = 0) {
super(prependCode(code), `Firebase Storage: ${message} (${prependCode(code)})`);
this.status_ = status_;
this.customData = { serverResponse: null };
this._baseMessage = this.message;
Object.setPrototypeOf(this, _StorageError.prototype);
}
get status() {
return this.status_;
}
set status(status) {
this.status_ = status;
}
/**
* Compares a `StorageErrorCode` against this error's code, filtering out the prefix.
*/
_codeEquals(code) {
return prependCode(code) === this.code;
}
/**
* Optional response message that was added by the server.
*/
get serverResponse() {
return this.customData.serverResponse;
}
set serverResponse(serverResponse) {
this.customData.serverResponse = serverResponse;
if (this.customData.serverResponse) {
this.message = `${this._baseMessage}
${this.customData.serverResponse}`;
} else {
this.message = this._baseMessage;
}
}
};
(function(StorageErrorCode2) {
StorageErrorCode2["UNKNOWN"] = "unknown";
StorageErrorCode2["OBJECT_NOT_FOUND"] = "object-not-found";
StorageErrorCode2["BUCKET_NOT_FOUND"] = "bucket-not-found";
StorageErrorCode2["PROJECT_NOT_FOUND"] = "project-not-found";
StorageErrorCode2["QUOTA_EXCEEDED"] = "quota-exceeded";
StorageErrorCode2["UNAUTHENTICATED"] = "unauthenticated";
StorageErrorCode2["UNAUTHORIZED"] = "unauthorized";
StorageErrorCode2["UNAUTHORIZED_APP"] = "unauthorized-app";
StorageErrorCode2["RETRY_LIMIT_EXCEEDED"] = "retry-limit-exceeded";
StorageErrorCode2["INVALID_CHECKSUM"] = "invalid-checksum";
StorageErrorCode2["CANCELED"] = "canceled";
StorageErrorCode2["INVALID_EVENT_NAME"] = "invalid-event-name";
StorageErrorCode2["INVALID_URL"] = "invalid-url";
StorageErrorCode2["INVALID_DEFAULT_BUCKET"] = "invalid-default-bucket";
StorageErrorCode2["NO_DEFAULT_BUCKET"] = "no-default-bucket";
StorageErrorCode2["CANNOT_SLICE_BLOB"] = "cannot-slice-blob";
StorageErrorCode2["SERVER_FILE_WRONG_SIZE"] = "server-file-wrong-size";
StorageErrorCode2["NO_DOWNLOAD_URL"] = "no-download-url";
StorageErrorCode2["INVALID_ARGUMENT"] = "invalid-argument";
StorageErrorCode2["INVALID_ARGUMENT_COUNT"] = "invalid-argument-count";
StorageErrorCode2["APP_DELETED"] = "app-deleted";
StorageErrorCode2["INVALID_ROOT_OPERATION"] = "invalid-root-operation";
StorageErrorCode2["INVALID_FORMAT"] = "invalid-format";
StorageErrorCode2["INTERNAL_ERROR"] = "internal-error";
StorageErrorCode2["UNSUPPORTED_ENVIRONMENT"] = "unsupported-environment";
})(StorageErrorCode || (StorageErrorCode = {}));
Location = class _Location {
constructor(bucket, path) {
this.bucket = bucket;
this.path_ = path;
}
get path() {
return this.path_;
}
get isRoot() {
return this.path.length === 0;
}
fullServerUrl() {
const encode2 = encodeURIComponent;
return "/b/" + encode2(this.bucket) + "/o/" + encode2(this.path);
}
bucketOnlyServerUrl() {
const encode2 = encodeURIComponent;
return "/b/" + encode2(this.bucket) + "/o";
}
static makeFromBucketSpec(bucketString, host) {
let bucketLocation;
try {
bucketLocation = _Location.makeFromUrl(bucketString, host);
} catch (e) {
return new _Location(bucketString, "");
}
if (bucketLocation.path === "") {
return bucketLocation;
} else {
throw invalidDefaultBucket(bucketString);
}
}
static makeFromUrl(url, host) {
let location = null;
const bucketDomain = "([A-Za-z0-9.\\-_]+)";
function gsModify(loc) {
if (loc.path.charAt(loc.path.length - 1) === "/") {
loc.path_ = loc.path_.slice(0, -1);
}
}
const gsPath = "(/(.*))?$";
const gsRegex = new RegExp("^gs://" + bucketDomain + gsPath, "i");
const gsIndices = { bucket: 1, path: 3 };
function httpModify(loc) {
loc.path_ = decodeURIComponent(loc.path);
}
const version6 = "v[A-Za-z0-9_]+";
const firebaseStorageHost = host.replace(/[.]/g, "\\.");
const firebaseStoragePath = "(/([^?#]*).*)?$";
const firebaseStorageRegExp = new RegExp(`^https?://${firebaseStorageHost}/${version6}/b/${bucketDomain}/o${firebaseStoragePath}`, "i");
const firebaseStorageIndices = { bucket: 1, path: 3 };
const cloudStorageHost = host === DEFAULT_HOST ? "(?:storage.googleapis.com|storage.cloud.google.com)" : host;
const cloudStoragePath = "([^?#]*)";
const cloudStorageRegExp = new RegExp(`^https?://${cloudStorageHost}/${bucketDomain}/${cloudStoragePath}`, "i");
const cloudStorageIndices = { bucket: 1, path: 2 };
const groups = [
{ regex: gsRegex, indices: gsIndices, postModify: gsModify },
{
regex: firebaseStorageRegExp,
indices: firebaseStorageIndices,
postModify: httpModify
},
{
regex: cloudStorageRegExp,
indices: cloudStorageIndices,
postModify: httpModify
}
];
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
const captures = group.regex.exec(url);
if (captures) {
const bucketValue = captures[group.indices.bucket];
let pathValue = captures[group.indices.path];
if (!pathValue) {
pathValue = "";
}
location = new _Location(bucketValue, pathValue);
group.postModify(location);
break;
}
}
if (location == null) {
throw invalidUrl(url);
}
return location;
}
};
FailRequest = class {
constructor(error) {
this.promise_ = Promise.reject(error);
}
/** @inheritDoc */
getPromise() {
return this.promise_;
}
/** @inheritDoc */
cancel(_appDelete = false) {
}
};
(function(ErrorCode2) {
ErrorCode2[ErrorCode2["NO_ERROR"] = 0] = "NO_ERROR";
ErrorCode2[ErrorCode2["NETWORK_ERROR"] = 1] = "NETWORK_ERROR";
ErrorCode2[ErrorCode2["ABORT"] = 2] = "ABORT";
})(ErrorCode || (ErrorCode = {}));
NetworkRequest = class {
constructor(url_, method_, headers_, body_, successCodes_, additionalRetryCodes_, callback_, errorCallback_, timeout_, progressCallback_, connectionFactory_, retry = true, isUsingEmulator = false) {
this.url_ = url_;
this.method_ = method_;
this.headers_ = headers_;
this.body_ = body_;
this.successCodes_ = successCodes_;
this.additionalRetryCodes_ = additionalRetryCodes_;
this.callback_ = callback_;
this.errorCallback_ = errorCallback_;
this.timeout_ = timeout_;
this.progressCallback_ = progressCallback_;
this.connectionFactory_ = connectionFactory_;
this.retry = retry;
this.isUsingEmulator = isUsingEmulator;
this.pendingConnection_ = null;
this.backoffId_ = null;
this.canceled_ = false;
this.appDelete_ = false;
this.promise_ = new Promise((resolve, reject) => {
this.resolve_ = resolve;
this.reject_ = reject;
this.start_();
});
}
/**
* Actually starts the retry loop.
*/
start_() {
const doTheRequest = (backoffCallback, canceled2) => {
if (canceled2) {
backoffCallback(false, new RequestEndStatus(false, null, true));
return;
}
const connection = this.connectionFactory_();
this.pendingConnection_ = connection;
const progressListener = (progressEvent) => {
const loaded = progressEvent.loaded;
const total = progressEvent.lengthComputable ? progressEvent.total : -1;
if (this.progressCallback_ !== null) {
this.progressCallback_(loaded, total);
}
};
if (this.progressCallback_ !== null) {
connection.addUploadProgressListener(progressListener);
}
connection.send(this.url_, this.method_, this.isUsingEmulator, this.body_, this.headers_).then(() => {
if (this.progressCallback_ !== null) {
connection.removeUploadProgressListener(progressListener);
}
this.pendingConnection_ = null;
const hitServer = connection.getErrorCode() === ErrorCode.NO_ERROR;
const status = connection.getStatus();
if (!hitServer || isRetryStatusCode(status, this.additionalRetryCodes_) && this.retry) {
const wasCanceled = connection.getErrorCode() === ErrorCode.ABORT;
backoffCallback(false, new RequestEndStatus(false, null, wasCanceled));
return;
}
const successCode = this.successCodes_.indexOf(status) !== -1;
backoffCallback(true, new RequestEndStatus(successCode, connection));
});
};
const backoffDone = (requestWentThrough, status) => {
const resolve = this.resolve_;
const reject = this.reject_;
const connection = status.connection;
if (status.wasSuccessCode) {
try {
const result = this.callback_(connection, connection.getResponse());
if (isJustDef(result)) {
resolve(result);
} else {
resolve();
}
} catch (e) {
reject(e);
}
} else {
if (connection !== null) {
const err = unknown();
err.serverResponse = connection.getErrorText();
if (this.errorCallback_) {
reject(this.errorCallback_(connection, err));
} else {
reject(err);
}
} else {
if (status.canceled) {
const err = this.appDelete_ ? appDeleted() : canceled();
reject(err);
} else {
const err = retryLimitExceeded();
reject(err);
}
}
}
};
if (this.canceled_) {
backoffDone(false, new RequestEndStatus(false, null, true));
} else {
this.backoffId_ = start(doTheRequest, backoffDone, this.timeout_);
}
}
/** @inheritDoc */
getPromise() {
return this.promise_;
}
/** @inheritDoc */
cancel(appDelete) {
this.canceled_ = true;
this.appDelete_ = appDelete || false;
if (this.backoffId_ !== null) {
stop(this.backoffId_);
}
if (this.pendingConnection_ !== null) {
this.pendingConnection_.abort();
}
}
};
RequestEndStatus = class {
constructor(wasSuccessCode, connection, canceled2) {
this.wasSuccessCode = wasSuccessCode;
this.connection = connection;
this.canceled = !!canceled2;
}
};
StringFormat = {
/**
* Indicates the string should be interpreted "raw", that is, as normal text.
* The string will be interpreted as UTF-16, then uploaded as a UTF-8 byte
* sequence.
* Example: The string 'Hello! \\ud83d\\ude0a' becomes the byte sequence
* 48 65 6c 6c 6f 21 20 f0 9f 98 8a
*/
RAW: "raw",
/**
* Indicates the string should be interpreted as base64-encoded data.
* Padding characters (trailing '='s) are optional.
* Example: The string 'rWmO++E6t7/rlw==' becomes the byte sequence
* ad 69 8e fb e1 3a b7 bf eb 97
*/
BASE64: "base64",
/**
* Indicates the string should be interpreted as base64url-encoded data.
* Padding characters (trailing '='s) are optional.
* Example: The string 'rWmO--E6t7_rlw==' becomes the byte sequence
* ad 69 8e fb e1 3a b7 bf eb 97
*/
BASE64URL: "base64url",
/**
* Indicates the string is a data URL, such as one obtained from
* canvas.toDataURL().
* Example: the string 'data:application/octet-stream;base64,aaaa'
* becomes the byte sequence
* 69 a6 9a
* (the content-type "application/octet-stream" is also applied, but can
* be overridden in the metadata object).
*/
DATA_URL: "data_url"
};
StringData = class {
constructor(data, contentType) {
this.data = data;
this.contentType = contentType || null;
}
};
DataURLParts = class {
constructor(dataURL) {
this.base64 = false;
this.contentType = null;
const matches = dataURL.match(/^data:([^,]+)?,/);
if (matches === null) {
throw invalidFormat(StringFormat.DATA_URL, "Must be formatted 'data:[<mediatype>][;base64],<data>");
}
const middle = matches[1] || null;
if (middle != null) {
this.base64 = endsWith(middle, ";base64");
this.contentType = this.base64 ? middle.substring(0, middle.length - ";base64".length) : middle;
}
this.rest = dataURL.substring(dataURL.indexOf(",") + 1);
}
};
FbsBlob = class _FbsBlob {
constructor(data, elideCopy) {
let size = 0;
let blobType = "";
if (isNativeBlob(data)) {
this.data_ = data;
size = data.size;
blobType = data.type;
} else if (data instanceof ArrayBuffer) {
if (elideCopy) {
this.data_ = new Uint8Array(data);
} else {
this.data_ = new Uint8Array(data.byteLength);
this.data_.set(new Uint8Array(data));
}
size = this.data_.length;
} else if (data instanceof Uint8Array) {
if (elideCopy) {
this.data_ = data;
} else {
this.data_ = new Uint8Array(data.length);
this.data_.set(data);
}
size = data.length;
}
this.size_ = size;
this.type_ = blobType;
}
size() {
return this.size_;
}
type() {
return this.type_;
}
slice(startByte, endByte) {
if (isNativeBlob(this.data_)) {
const realBlob = this.data_;
const sliced = sliceBlob(realBlob, startByte, endByte);
if (sliced === null) {
return null;
}
return new _FbsBlob(sliced);
} else {
const slice = new Uint8Array(this.data_.buffer, startByte, endByte - startByte);
return new _FbsBlob(slice, true);
}
}
static getBlob(...args) {
if (isNativeBlobDefined()) {
const blobby = args.map((val) => {
if (val instanceof _FbsBlob) {
return val.data_;
} else {
return val;
}
});
return new _FbsBlob(getBlob$1.apply(null, blobby));
} else {
const uint8Arrays = args.map((val) => {
if (isString(val)) {
return dataFromString(StringFormat.RAW, val).data;
} else {
return val.data_;
}
});
let finalLength = 0;
uint8Arrays.forEach((array) => {
finalLength += array.byteLength;
});
const merged = new Uint8Array(finalLength);
let index = 0;
uint8Arrays.forEach((array) => {
for (let i = 0; i < array.length; i++) {
merged[index++] = array[i];
}
});
return new _FbsBlob(merged, true);
}
}
uploadData() {
return this.data_;
}
};
Mapping = class {
constructor(server, local, writable, xform) {
this.server = server;
this.local = local || server;
this.writable = !!writable;
this.xform = xform || noXform_;
}
};
mappings_ = null;
RequestInfo = class {
constructor(url, method, handler, timeout) {
this.url = url;
this.method = method;
this.handler = handler;
this.timeout = timeout;
this.urlParams = {};
this.headers = {};
this.body = null;
this.errorHandler = null;
this.progressCallback = null;
this.successCodes = [200];
this.additionalRetryCodes = [];
}
};
RESUMABLE_UPLOAD_CHUNK_SIZE = 256 * 1024;
textFactoryOverride = null;
FetchConnection = class {
constructor() {
this.errorText_ = "";
this.sent_ = false;
this.errorCode_ = ErrorCode.NO_ERROR;
}
async send(url, method, isUsingEmulator, body, headers) {
if (this.sent_) {
throw internalError("cannot .send() more than once");
}
this.sent_ = true;
try {
const response = await newFetch(url, method, isUsingEmulator, headers, body);
this.headers_ = response.headers;
this.statusCode_ = response.status;
this.errorCode_ = ErrorCode.NO_ERROR;
this.body_ = await response.arrayBuffer();
} catch (e) {
this.errorText_ = e?.message;
this.statusCode_ = 0;
this.errorCode_ = ErrorCode.NETWORK_ERROR;
}
}
getErrorCode() {
if (this.errorCode_ === void 0) {
throw internalError("cannot .getErrorCode() before receiving response");
}
return this.errorCode_;
}
getStatus() {
if (this.statusCode_ === void 0) {
throw internalError("cannot .getStatus() before receiving response");
}
return this.statusCode_;
}
getErrorText() {
return this.errorText_;
}
abort() {
}
getResponseHeader(header) {
if (!this.headers_) {
throw internalError("cannot .getResponseHeader() before receiving response");
}
return this.headers_.get(header);
}
addUploadProgressListener(listener) {
}
removeUploadProgressListener(listener) {
}
};
FetchTextConnection = class extends FetchConnection {
getResponse() {
if (!this.body_) {
throw internalError("cannot .getResponse() before receiving response");
}
return Buffer.from(this.body_).toString("utf-8");
}
};
Reference = class _Reference {
constructor(_service, location) {
this._service = _service;
if (location instanceof Location) {
this._location = location;
} else {
this._location = Location.makeFromUrl(location, _service.host);
}
}
/**
* Returns the URL for the bucket and path this object references,
* in the form gs://<bucket>/<object-path>
* @override
*/
toString() {
return "gs://" + this._location.bucket + "/" + this._location.path;
}
_newRef(service, location) {
return new _Reference(service, location);
}
/**
* A reference to the root of this object's bucket.
*/
get root() {
const location = new Location(this._location.bucket, "");
return this._newRef(this._service, location);
}
/**
* The name of the bucket containing this reference's object.
*/
get bucket() {
return this._location.bucket;
}
/**
* The full path of this object.
*/
get fullPath() {
return this._location.path;
}
/**
* The short name of this object, which is the last component of the full path.
* For example, if fullPath is 'full/path/image.png', name is 'image.png'.
*/
get name() {
return lastComponent(this._location.path);
}
/**
* The `StorageService` instance this `StorageReference` is associated with.
*/
get storage() {
return this._service;
}
/**
* A `StorageReference` pointing to the parent location of this `StorageReference`, or null if
* this reference is the root.
*/
get parent() {
const newPath = parent(this._location.path);
if (newPath === null) {
return null;
}
const location = new Location(this._location.bucket, newPath);
return new _Reference(this._service, location);
}
/**
* Utility function to throw an error in methods that do not accept a root reference.
*/
_throwIfRoot(name6) {
if (this._location.path === "") {
throw invalidRootOperation(name6);
}
}
};
FirebaseStorageImpl = class {
constructor(app2, _authProvider, _appCheckProvider, _url, _firebaseVersion, _isUsingEmulator = false) {
this.app = app2;
this._authProvider = _authProvider;
this._appCheckProvider = _appCheckProvider;
this._url = _url;
this._firebaseVersion = _firebaseVersion;
this._isUsingEmulator = _isUsingEmulator;
this._bucket = null;
this._host = DEFAULT_HOST;
this._protocol = "https";
this._appId = null;
this._deleted = false;
this._maxOperationRetryTime = DEFAULT_MAX_OPERATION_RETRY_TIME;
this._maxUploadRetryTime = DEFAULT_MAX_UPLOAD_RETRY_TIME;
this._requests = /* @__PURE__ */ new Set();
if (_url != null) {
this._bucket = Location.makeFromBucketSpec(_url, this._host);
} else {
this._bucket = extractBucket(this._host, this.app.options);
}
}
/**
* The host string for this service, in the form of `host` or
* `host:port`.
*/
get host() {
return this._host;
}
set host(host) {
this._host = host;
if (this._url != null) {
this._bucket = Location.makeFromBucketSpec(this._url, host);
} else {
this._bucket = extractBucket(host, this.app.options);
}
}
/**
* The maximum time to retry uploads in milliseconds.
*/
get maxUploadRetryTime() {
return this._maxUploadRetryTime;
}
set maxUploadRetryTime(time) {
validateNumber(
"time",
/* minValue=*/
0,
/* maxValue= */
Number.POSITIVE_INFINITY,
time
);
this._maxUploadRetryTime = time;
}
/**
* The maximum time to retry operations other than uploads or downloads in
* milliseconds.
*/
get maxOperationRetryTime() {
return this._maxOperationRetryTime;
}
set maxOperationRetryTime(time) {
validateNumber(
"time",
/* minValue=*/
0,
/* maxValue= */
Number.POSITIVE_INFINITY,
time
);
this._maxOperationRetryTime = time;
}
async _getAuthToken() {
if (this._overrideAuthToken) {
return this._overrideAuthToken;
}
const auth2 = this._authProvider.getImmediate({ optional: true });
if (auth2) {
const tokenData = await auth2.getToken();
if (tokenData !== null) {
return tokenData.accessToken;
}
}
return null;
}
async _getAppCheckToken() {
if (_isFirebaseServerApp(this.app) && this.app.settings.appCheckToken) {
return this.app.settings.appCheckToken;
}
const appCheck = this._appCheckProvider.getImmediate({ optional: true });
if (appCheck) {
const result = await appCheck.getToken();
return result.token;
}
return null;
}
/**
* Stop running requests and prevent more from being created.
*/
_delete() {
if (!this._deleted) {
this._deleted = true;
this._requests.forEach((request) => request.cancel());
this._requests.clear();
}
return Promise.resolve();
}
/**
* Returns a new firebaseStorage.Reference object referencing this StorageService
* at the given Location.
*/
_makeStorageReference(loc) {
return new Reference(this, loc);
}
/**
* @param requestInfo - HTTP RequestInfo object
* @param authToken - Firebase auth token
*/
_makeRequest(requestInfo, requestFactory, authToken, appCheckToken, retry = true) {
if (!this._deleted) {
const request = makeRequest(requestInfo, this._appId, authToken, appCheckToken, requestFactory, this._firebaseVersion, retry, this._isUsingEmulator);
this._requests.add(request);
request.getPromise().then(() => this._requests.delete(request), () => this._requests.delete(request));
return request;
} else {
return new FailRequest(appDeleted());
}
}
async makeRequestWithTokens(requestInfo, requestFactory) {
const [authToken, appCheckToken] = await Promise.all([
this._getAuthToken(),
this._getAppCheckToken()
]);
return this._makeRequest(requestInfo, requestFactory, authToken, appCheckToken).getPromise();
}
};
name5 = "@firebase/storage";
version5 = "0.14.0";
STORAGE_TYPE = "storage";
registerStorage();
}
});
// node_modules/firebase/storage/dist/index.mjs
var init_dist4 = __esm({
"node_modules/firebase/storage/dist/index.mjs"() {
init_index_node_esm2();
}
});
// src/firebase-config.ts
var firebase_config_exports = {};
__export(firebase_config_exports, {
app: () => app,
auth: () => auth,
functions: () => functions,
storage: () => storage
});
var firebaseConfig, app, auth, functions, storage;
var init_firebase_config = __esm({
"src/firebase-config.ts"() {
"use strict";
init_dist();
init_dist2();
init_dist3();
init_dist4();
firebaseConfig = {
apiKey: "AIzaSyD_qH-0Gr_pdmNLOQW5pea2BbiyHpxstN8",
authDomain: "uuu-gl.firebaseapp.com",
projectId: "uuu-gl",
storageBucket: "uuu-gl.firebasestorage.app",
messagingSenderId: "484571716021",
appId: "1:484571716021:web:25ca37bf90f320cf07a1fc"
};
app = initializeApp(firebaseConfig);
auth = getAuth(app);
functions = getFunctions(app, "us-central1");
storage = getStorage(app);
}
});
// node_modules/@fingerprintjs/fingerprintjs/dist/fp.cjs.js
var require_fp_cjs = __commonJS({
"node_modules/@fingerprintjs/fingerprintjs/dist/fp.cjs.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var version6 = "5.0.1";
function wait(durationMs, resolveWith) {
return new Promise((resolve) => setTimeout(resolve, durationMs, resolveWith));
}
function releaseEventLoop() {
return new Promise((resolve) => {
const channel = new MessageChannel();
channel.port1.onmessage = () => resolve();
channel.port2.postMessage(null);
});
}
function requestIdleCallbackIfAvailable(fallbackTimeout, deadlineTimeout = Infinity) {
const { requestIdleCallback } = window;
if (requestIdleCallback) {
return new Promise((resolve) => requestIdleCallback.call(window, () => resolve(), { timeout: deadlineTimeout }));
} else {
return wait(Math.min(fallbackTimeout, deadlineTimeout));
}
}
function isPromise(value) {
return !!value && typeof value.then === "function";
}
function awaitIfAsync(action, callback) {
try {
const returnedValue = action();
if (isPromise(returnedValue)) {
returnedValue.then((result) => callback(true, result), (error) => callback(false, error));
} else {
callback(true, returnedValue);
}
} catch (error) {
callback(false, error);
}
}
async function mapWithBreaks(items, callback, loopReleaseInterval = 16) {
const results = Array(items.length);
let lastLoopReleaseTime = Date.now();
for (let i = 0; i < items.length; ++i) {
results[i] = callback(items[i], i);
const now = Date.now();
if (now >= lastLoopReleaseTime + loopReleaseInterval) {
lastLoopReleaseTime = now;
await releaseEventLoop();
}
}
return results;
}
function suppressUnhandledRejectionWarning(promise) {
promise.then(void 0, () => void 0);
return promise;
}
function includes(haystack, needle) {
for (let i = 0, l = haystack.length; i < l; ++i) {
if (haystack[i] === needle) {
return true;
}
}
return false;
}
function excludes(haystack, needle) {
return !includes(haystack, needle);
}
function toInt(value) {
return parseInt(value);
}
function toFloat(value) {
return parseFloat(value);
}
function replaceNaN(value, replacement) {
return typeof value === "number" && isNaN(value) ? replacement : value;
}
function countTruthy(values) {
return values.reduce((sum, value) => sum + (value ? 1 : 0), 0);
}
function round(value, base = 1) {
if (Math.abs(base) >= 1) {
return Math.round(value / base) * base;
} else {
const counterBase = 1 / base;
return Math.round(value * counterBase) / counterBase;
}
}
function parseSimpleCssSelector(selector) {
var _a, _b;
const errorMessage = `Unexpected syntax '${selector}'`;
const tagMatch = /^\s*([a-z-]*)(.*)$/i.exec(selector);
const tag = tagMatch[1] || void 0;
const attributes = {};
const partsRegex = /([.:#][\w-]+|\[.+?\])/gi;
const addAttribute = (name6, value) => {
attributes[name6] = attributes[name6] || [];
attributes[name6].push(value);
};
for (; ; ) {
const match = partsRegex.exec(tagMatch[2]);
if (!match) {
break;
}
const part = match[0];
switch (part[0]) {
case ".":
addAttribute("class", part.slice(1));
break;
case "#":
addAttribute("id", part.slice(1));
break;
case "[": {
const attributeMatch = /^\[([\w-]+)([~|^$*]?=("(.*?)"|([\w-]+)))?(\s+[is])?\]$/.exec(part);
if (attributeMatch) {
addAttribute(attributeMatch[1], (_b = (_a = attributeMatch[4]) !== null && _a !== void 0 ? _a : attributeMatch[5]) !== null && _b !== void 0 ? _b : "");
} else {
throw new Error(errorMessage);
}
break;
}
default:
throw new Error(errorMessage);
}
}
return [tag, attributes];
}
function getUTF8Bytes(input) {
const result = new Uint8Array(input.length);
for (let i = 0; i < input.length; i++) {
const charCode = input.charCodeAt(i);
if (charCode > 127) {
return new TextEncoder().encode(input);
}
result[i] = charCode;
}
return result;
}
function x64Add(m, n) {
const m0 = m[0] >>> 16, m1 = m[0] & 65535, m2 = m[1] >>> 16, m3 = m[1] & 65535;
const n0 = n[0] >>> 16, n1 = n[0] & 65535, n2 = n[1] >>> 16, n3 = n[1] & 65535;
let o0 = 0, o1 = 0, o2 = 0, o3 = 0;
o3 += m3 + n3;
o2 += o3 >>> 16;
o3 &= 65535;
o2 += m2 + n2;
o1 += o2 >>> 16;
o2 &= 65535;
o1 += m1 + n1;
o0 += o1 >>> 16;
o1 &= 65535;
o0 += m0 + n0;
o0 &= 65535;
m[0] = o0 << 16 | o1;
m[1] = o2 << 16 | o3;
}
function x64Multiply(m, n) {
const m0 = m[0] >>> 16, m1 = m[0] & 65535, m2 = m[1] >>> 16, m3 = m[1] & 65535;
const n0 = n[0] >>> 16, n1 = n[0] & 65535, n2 = n[1] >>> 16, n3 = n[1] & 65535;
let o0 = 0, o1 = 0, o2 = 0, o3 = 0;
o3 += m3 * n3;
o2 += o3 >>> 16;
o3 &= 65535;
o2 += m2 * n3;
o1 += o2 >>> 16;
o2 &= 65535;
o2 += m3 * n2;
o1 += o2 >>> 16;
o2 &= 65535;
o1 += m1 * n3;
o0 += o1 >>> 16;
o1 &= 65535;
o1 += m2 * n2;
o0 += o1 >>> 16;
o1 &= 65535;
o1 += m3 * n1;
o0 += o1 >>> 16;
o1 &= 65535;
o0 += m0 * n3 + m1 * n2 + m2 * n1 + m3 * n0;
o0 &= 65535;
m[0] = o0 << 16 | o1;
m[1] = o2 << 16 | o3;
}
function x64Rotl(m, bits) {
const m0 = m[0];
bits %= 64;
if (bits === 32) {
m[0] = m[1];
m[1] = m0;
} else if (bits < 32) {
m[0] = m0 << bits | m[1] >>> 32 - bits;
m[1] = m[1] << bits | m0 >>> 32 - bits;
} else {
bits -= 32;
m[0] = m[1] << bits | m0 >>> 32 - bits;
m[1] = m0 << bits | m[1] >>> 32 - bits;
}
}
function x64LeftShift(m, bits) {
bits %= 64;
if (bits === 0) {
return;
} else if (bits < 32) {
m[0] = m[1] >>> 32 - bits;
m[1] = m[1] << bits;
} else {
m[0] = m[1] << bits - 32;
m[1] = 0;
}
}
function x64Xor(m, n) {
m[0] ^= n[0];
m[1] ^= n[1];
}
var F1 = [4283543511, 3981806797];
var F2 = [3301882366, 444984403];
function x64Fmix(h) {
const shifted = [0, h[0] >>> 1];
x64Xor(h, shifted);
x64Multiply(h, F1);
shifted[1] = h[0] >>> 1;
x64Xor(h, shifted);
x64Multiply(h, F2);
shifted[1] = h[0] >>> 1;
x64Xor(h, shifted);
}
var C1 = [2277735313, 289559509];
var C2 = [1291169091, 658871167];
var M$1 = [0, 5];
var N1 = [0, 1390208809];
var N2 = [0, 944331445];
function x64hash128(input, seed) {
const key = getUTF8Bytes(input);
seed = seed || 0;
const length = [0, key.length];
const remainder = length[1] % 16;
const bytes = length[1] - remainder;
const h1 = [0, seed];
const h2 = [0, seed];
const k1 = [0, 0];
const k2 = [0, 0];
let i;
for (i = 0; i < bytes; i = i + 16) {
k1[0] = key[i + 4] | key[i + 5] << 8 | key[i + 6] << 16 | key[i + 7] << 24;
k1[1] = key[i] | key[i + 1] << 8 | key[i + 2] << 16 | key[i + 3] << 24;
k2[0] = key[i + 12] | key[i + 13] << 8 | key[i + 14] << 16 | key[i + 15] << 24;
k2[1] = key[i + 8] | key[i + 9] << 8 | key[i + 10] << 16 | key[i + 11] << 24;
x64Multiply(k1, C1);
x64Rotl(k1, 31);
x64Multiply(k1, C2);
x64Xor(h1, k1);
x64Rotl(h1, 27);
x64Add(h1, h2);
x64Multiply(h1, M$1);
x64Add(h1, N1);
x64Multiply(k2, C2);
x64Rotl(k2, 33);
x64Multiply(k2, C1);
x64Xor(h2, k2);
x64Rotl(h2, 31);
x64Add(h2, h1);
x64Multiply(h2, M$1);
x64Add(h2, N2);
}
k1[0] = 0;
k1[1] = 0;
k2[0] = 0;
k2[1] = 0;
const val = [0, 0];
switch (remainder) {
case 15:
val[1] = key[i + 14];
x64LeftShift(val, 48);
x64Xor(k2, val);
// fallthrough
case 14:
val[1] = key[i + 13];
x64LeftShift(val, 40);
x64Xor(k2, val);
// fallthrough
case 13:
val[1] = key[i + 12];
x64LeftShift(val, 32);
x64Xor(k2, val);
// fallthrough
case 12:
val[1] = key[i + 11];
x64LeftShift(val, 24);
x64Xor(k2, val);
// fallthrough
case 11:
val[1] = key[i + 10];
x64LeftShift(val, 16);
x64Xor(k2, val);
// fallthrough
case 10:
val[1] = key[i + 9];
x64LeftShift(val, 8);
x64Xor(k2, val);
// fallthrough
case 9:
val[1] = key[i + 8];
x64Xor(k2, val);
x64Multiply(k2, C2);
x64Rotl(k2, 33);
x64Multiply(k2, C1);
x64Xor(h2, k2);
// fallthrough
case 8:
val[1] = key[i + 7];
x64LeftShift(val, 56);
x64Xor(k1, val);
// fallthrough
case 7:
val[1] = key[i + 6];
x64LeftShift(val, 48);
x64Xor(k1, val);
// fallthrough
case 6:
val[1] = key[i + 5];
x64LeftShift(val, 40);
x64Xor(k1, val);
// fallthrough
case 5:
val[1] = key[i + 4];
x64LeftShift(val, 32);
x64Xor(k1, val);
// fallthrough
case 4:
val[1] = key[i + 3];
x64LeftShift(val, 24);
x64Xor(k1, val);
// fallthrough
case 3:
val[1] = key[i + 2];
x64LeftShift(val, 16);
x64Xor(k1, val);
// fallthrough
case 2:
val[1] = key[i + 1];
x64LeftShift(val, 8);
x64Xor(k1, val);
// fallthrough
case 1:
val[1] = key[i];
x64Xor(k1, val);
x64Multiply(k1, C1);
x64Rotl(k1, 31);
x64Multiply(k1, C2);
x64Xor(h1, k1);
}
x64Xor(h1, length);
x64Xor(h2, length);
x64Add(h1, h2);
x64Add(h2, h1);
x64Fmix(h1);
x64Fmix(h2);
x64Add(h1, h2);
x64Add(h2, h1);
return ("00000000" + (h1[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h1[1] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[1] >>> 0).toString(16)).slice(-8);
}
function errorToObject(error) {
var _a;
return {
name: error.name,
message: error.message,
stack: (_a = error.stack) === null || _a === void 0 ? void 0 : _a.split("\n"),
// The fields are not enumerable, so TS is wrong saying that they will be overridden
...error
};
}
function isFunctionNative(func) {
return /^function\s.*?\{\s*\[native code]\s*}$/.test(String(func));
}
function isFinalResultLoaded(loadResult) {
return typeof loadResult !== "function";
}
function loadSource(source, sourceOptions) {
const sourceLoadPromise = suppressUnhandledRejectionWarning(new Promise((resolveLoad) => {
const loadStartTime = Date.now();
awaitIfAsync(source.bind(null, sourceOptions), (...loadArgs) => {
const loadDuration = Date.now() - loadStartTime;
if (!loadArgs[0]) {
return resolveLoad(() => ({ error: loadArgs[1], duration: loadDuration }));
}
const loadResult = loadArgs[1];
if (isFinalResultLoaded(loadResult)) {
return resolveLoad(() => ({ value: loadResult, duration: loadDuration }));
}
resolveLoad(() => new Promise((resolveGet) => {
const getStartTime = Date.now();
awaitIfAsync(loadResult, (...getArgs) => {
const duration = loadDuration + Date.now() - getStartTime;
if (!getArgs[0]) {
return resolveGet({ error: getArgs[1], duration });
}
resolveGet({ value: getArgs[1], duration });
});
}));
});
}));
return function getComponent() {
return sourceLoadPromise.then((finalizeSource) => finalizeSource());
};
}
function loadSources(sources2, sourceOptions, excludeSources, loopReleaseInterval) {
const includedSources = Object.keys(sources2).filter((sourceKey) => excludes(excludeSources, sourceKey));
const sourceGettersPromise = suppressUnhandledRejectionWarning(mapWithBreaks(includedSources, (sourceKey) => loadSource(sources2[sourceKey], sourceOptions), loopReleaseInterval));
return async function getComponents() {
const sourceGetters = await sourceGettersPromise;
const componentPromises = await mapWithBreaks(sourceGetters, (sourceGetter) => suppressUnhandledRejectionWarning(sourceGetter()), loopReleaseInterval);
const componentArray = await Promise.all(componentPromises);
const components = {};
for (let index2 = 0; index2 < includedSources.length; ++index2) {
components[includedSources[index2]] = componentArray[index2];
}
return components;
};
}
function transformSource(source, transformValue) {
const transformLoadResult = (loadResult) => {
if (isFinalResultLoaded(loadResult)) {
return transformValue(loadResult);
}
return () => {
const getResult = loadResult();
if (isPromise(getResult)) {
return getResult.then(transformValue);
}
return transformValue(getResult);
};
};
return (options) => {
const loadResult = source(options);
if (isPromise(loadResult)) {
return loadResult.then(transformLoadResult);
}
return transformLoadResult(loadResult);
};
}
function isTrident() {
const w = window;
const n = navigator;
return countTruthy([
"MSCSSMatrix" in w,
"msSetImmediate" in w,
"msIndexedDB" in w,
"msMaxTouchPoints" in n,
"msPointerEnabled" in n
]) >= 4;
}
function isEdgeHTML() {
const w = window;
const n = navigator;
return countTruthy(["msWriteProfilerMark" in w, "MSStream" in w, "msLaunchUri" in n, "msSaveBlob" in n]) >= 3 && !isTrident();
}
function isChromium() {
const w = window;
const n = navigator;
return countTruthy([
"webkitPersistentStorage" in n,
"webkitTemporaryStorage" in n,
(n.vendor || "").indexOf("Google") === 0,
"webkitResolveLocalFileSystemURL" in w,
"BatteryManager" in w,
"webkitMediaStream" in w,
"webkitSpeechGrammar" in w
]) >= 5;
}
function isWebKit() {
const w = window;
const n = navigator;
return countTruthy([
"ApplePayError" in w,
"CSSPrimitiveValue" in w,
"Counter" in w,
n.vendor.indexOf("Apple") === 0,
"RGBColor" in w,
"WebKitMediaKeys" in w
]) >= 4;
}
function isDesktopWebKit() {
const w = window;
const { HTMLElement, Document } = w;
return countTruthy([
"safari" in w,
!("ongestureend" in w),
!("TouchEvent" in w),
!("orientation" in w),
HTMLElement && !("autocapitalize" in HTMLElement.prototype),
Document && "pointerLockElement" in Document.prototype
]) >= 4;
}
function isSafariWebKit() {
const w = window;
return (
// Filters-out Chrome, Yandex, DuckDuckGo (macOS and iOS), Edge
isFunctionNative(w.print) && // Doesn't work in Safari < 15.4
String(w.browser) === "[object WebPageNamespace]"
);
}
function isGecko() {
var _a, _b;
const w = window;
return countTruthy([
"buildID" in navigator,
"MozAppearance" in ((_b = (_a = document.documentElement) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {}),
"onmozfullscreenchange" in w,
"mozInnerScreenX" in w,
"CSSMozDocumentRule" in w,
"CanvasCaptureMediaStream" in w
]) >= 4;
}
function isChromium86OrNewer() {
const w = window;
return countTruthy([
!("MediaSettingsRange" in w),
"RTCEncodedAudioFrame" in w,
"" + w.Intl === "[object Intl]",
"" + w.Reflect === "[object Reflect]"
]) >= 3;
}
function isChromium122OrNewer() {
const w = window;
const { URLPattern } = w;
return countTruthy([
"union" in Set.prototype,
"Iterator" in w,
URLPattern && "hasRegExpGroups" in URLPattern.prototype,
"RGB8" in WebGLRenderingContext.prototype
]) >= 3;
}
function isWebKit606OrNewer() {
const w = window;
return countTruthy([
"DOMRectList" in w,
"RTCPeerConnectionIceEvent" in w,
"SVGGeometryElement" in w,
"ontransitioncancel" in w
]) >= 3;
}
function isWebKit616OrNewer() {
const w = window;
const n = navigator;
const { CSS, HTMLButtonElement } = w;
return countTruthy([
!("getStorageUpdates" in n),
HTMLButtonElement && "popover" in HTMLButtonElement.prototype,
"CSSCounterStyleRule" in w,
CSS.supports("font-size-adjust: ex-height 0.5"),
CSS.supports("text-transform: full-width")
]) >= 4;
}
function isIPad() {
if (navigator.platform === "iPad") {
return true;
}
const s = screen;
const screenRatio = s.width / s.height;
return countTruthy([
// Since iOS 13. Doesn't work in Chrome on iPadOS <15, but works in desktop mode.
"MediaSource" in window,
// Since iOS 12. Doesn't work in Chrome on iPadOS.
!!Element.prototype.webkitRequestFullscreen,
// iPhone 4S that runs iOS 9 matches this, but it is not supported
// Doesn't work in incognito mode of Safari ≥17 with split screen because of tracking prevention
screenRatio > 0.65 && screenRatio < 1.53
]) >= 2;
}
function getFullscreenElement() {
const d = document;
return d.fullscreenElement || d.msFullscreenElement || d.mozFullScreenElement || d.webkitFullscreenElement || null;
}
function exitFullscreen() {
const d = document;
return (d.exitFullscreen || d.msExitFullscreen || d.mozCancelFullScreen || d.webkitExitFullscreen).call(d);
}
function isAndroid() {
const isItChromium = isChromium();
const isItGecko = isGecko();
const w = window;
const n = navigator;
const c = "connection";
if (isItChromium) {
return countTruthy([
!("SharedWorker" in w),
// `typechange` is deprecated, but it's still present on Android (tested on Chrome Mobile 117)
// Removal proposal https://bugs.chromium.org/p/chromium/issues/detail?id=699892
// Note: this expression returns true on ChromeOS, so additional detectors are required to avoid false-positives
n[c] && "ontypechange" in n[c],
!("sinkId" in new Audio())
]) >= 2;
} else if (isItGecko) {
return countTruthy(["onorientationchange" in w, "orientation" in w, /android/i.test(n.appVersion)]) >= 2;
} else {
return false;
}
}
function isSamsungInternet() {
const n = navigator;
const w = window;
const audioPrototype = Audio.prototype;
const { visualViewport } = w;
return countTruthy([
"srLatency" in audioPrototype,
"srChannelCount" in audioPrototype,
"devicePosture" in n,
visualViewport && "segments" in visualViewport,
"getTextInformation" in Image.prototype
// Not available in Samsung Internet 21
]) >= 3;
}
function getAudioFingerprint() {
if (doesBrowserPerformAntifingerprinting$1()) {
return -4;
}
return getUnstableAudioFingerprint();
}
function getUnstableAudioFingerprint() {
const w = window;
const AudioContext2 = w.OfflineAudioContext || w.webkitOfflineAudioContext;
if (!AudioContext2) {
return -2;
}
if (doesBrowserSuspendAudioContext()) {
return -1;
}
const hashFromIndex = 4500;
const hashToIndex = 5e3;
const context = new AudioContext2(1, hashToIndex, 44100);
const oscillator = context.createOscillator();
oscillator.type = "triangle";
oscillator.frequency.value = 1e4;
const compressor = context.createDynamicsCompressor();
compressor.threshold.value = -50;
compressor.knee.value = 40;
compressor.ratio.value = 12;
compressor.attack.value = 0;
compressor.release.value = 0.25;
oscillator.connect(compressor);
compressor.connect(context.destination);
oscillator.start(0);
const [renderPromise, finishRendering] = startRenderingAudio(context);
const fingerprintPromise = suppressUnhandledRejectionWarning(renderPromise.then((buffer) => getHash(buffer.getChannelData(0).subarray(hashFromIndex)), (error) => {
if (error.name === "timeout" || error.name === "suspended") {
return -3;
}
throw error;
}));
return () => {
finishRendering();
return fingerprintPromise;
};
}
function doesBrowserSuspendAudioContext() {
return isWebKit() && !isDesktopWebKit() && !isWebKit606OrNewer();
}
function doesBrowserPerformAntifingerprinting$1() {
return (
// Safari ≥17
isWebKit() && isWebKit616OrNewer() && isSafariWebKit() || // Samsung Internet ≥26
isChromium() && isSamsungInternet() && isChromium122OrNewer()
);
}
function startRenderingAudio(context) {
const renderTryMaxCount = 3;
const renderRetryDelay = 500;
const runningMaxAwaitTime = 500;
const runningSufficientTime = 5e3;
let finalize = () => void 0;
const resultPromise = new Promise((resolve, reject) => {
let isFinalized = false;
let renderTryCount = 0;
let startedRunningAt = 0;
context.oncomplete = (event) => resolve(event.renderedBuffer);
const startRunningTimeout = () => {
setTimeout(() => reject(makeInnerError(
"timeout"
/* InnerErrorName.Timeout */
)), Math.min(runningMaxAwaitTime, startedRunningAt + runningSufficientTime - Date.now()));
};
const tryRender = () => {
try {
const renderingPromise = context.startRendering();
if (isPromise(renderingPromise)) {
suppressUnhandledRejectionWarning(renderingPromise);
}
switch (context.state) {
case "running":
startedRunningAt = Date.now();
if (isFinalized) {
startRunningTimeout();
}
break;
// Sometimes the audio context doesn't start after calling `startRendering` (in addition to the cases where
// audio context doesn't start at all). A known case is starting an audio context when the browser tab is in
// background on iPhone. Retries usually help in this case.
case "suspended":
if (!document.hidden) {
renderTryCount++;
}
if (isFinalized && renderTryCount >= renderTryMaxCount) {
reject(makeInnerError(
"suspended"
/* InnerErrorName.Suspended */
));
} else {
setTimeout(tryRender, renderRetryDelay);
}
break;
}
} catch (error) {
reject(error);
}
};
tryRender();
finalize = () => {
if (!isFinalized) {
isFinalized = true;
if (startedRunningAt > 0) {
startRunningTimeout();
}
}
};
});
return [resultPromise, finalize];
}
function getHash(signal) {
let hash = 0;
for (let i = 0; i < signal.length; ++i) {
hash += Math.abs(signal[i]);
}
return hash;
}
function makeInnerError(name6) {
const error = new Error(name6);
error.name = name6;
return error;
}
async function withIframe(action, initialHtml, domPollInterval = 50) {
var _a, _b, _c;
const d = document;
while (!d.body) {
await wait(domPollInterval);
}
const iframe = d.createElement("iframe");
try {
await new Promise((_resolve, _reject) => {
let isComplete = false;
const resolve = () => {
isComplete = true;
_resolve();
};
const reject = (error) => {
isComplete = true;
_reject(error);
};
iframe.onload = resolve;
iframe.onerror = reject;
const { style } = iframe;
style.setProperty("display", "block", "important");
style.position = "absolute";
style.top = "0";
style.left = "0";
style.visibility = "hidden";
if (initialHtml && "srcdoc" in iframe) {
iframe.srcdoc = initialHtml;
} else {
iframe.src = "about:blank";
}
d.body.appendChild(iframe);
const checkReadyState = () => {
var _a2, _b2;
if (isComplete) {
return;
}
if (((_b2 = (_a2 = iframe.contentWindow) === null || _a2 === void 0 ? void 0 : _a2.document) === null || _b2 === void 0 ? void 0 : _b2.readyState) === "complete") {
resolve();
} else {
setTimeout(checkReadyState, 10);
}
};
checkReadyState();
});
while (!((_b = (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.document) === null || _b === void 0 ? void 0 : _b.body)) {
await wait(domPollInterval);
}
return await action(iframe, iframe.contentWindow);
} finally {
(_c = iframe.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(iframe);
}
}
function selectorToElement(selector) {
const [tag, attributes] = parseSimpleCssSelector(selector);
const element = document.createElement(tag !== null && tag !== void 0 ? tag : "div");
for (const name6 of Object.keys(attributes)) {
const value = attributes[name6].join(" ");
if (name6 === "style") {
addStyleString(element.style, value);
} else {
element.setAttribute(name6, value);
}
}
return element;
}
function addStyleString(style, source) {
for (const property of source.split(";")) {
const match = /^\s*([\w-]+)\s*:\s*(.+?)(\s*!([\w-]+))?\s*$/.exec(property);
if (match) {
const [, name6, value, , priority] = match;
style.setProperty(name6, value, priority || "");
}
}
}
function isAnyParentCrossOrigin() {
let currentWindow = window;
for (; ; ) {
const parentWindow = currentWindow.parent;
if (!parentWindow || parentWindow === currentWindow) {
return false;
}
try {
if (parentWindow.location.origin !== currentWindow.location.origin) {
return true;
}
} catch (error) {
if (error instanceof Error && error.name === "SecurityError") {
return true;
}
throw error;
}
currentWindow = parentWindow;
}
}
var testString = "mmMwWLliI0O&1";
var textSize = "48px";
var baseFonts = ["monospace", "sans-serif", "serif"];
var fontList = [
// This is android-specific font from "Roboto" family
"sans-serif-thin",
"ARNO PRO",
"Agency FB",
"Arabic Typesetting",
"Arial Unicode MS",
"AvantGarde Bk BT",
"BankGothic Md BT",
"Batang",
"Bitstream Vera Sans Mono",
"Calibri",
"Century",
"Century Gothic",
"Clarendon",
"EUROSTILE",
"Franklin Gothic",
"Futura Bk BT",
"Futura Md BT",
"GOTHAM",
"Gill Sans",
"HELV",
"Haettenschweiler",
"Helvetica Neue",
"Humanst521 BT",
"Leelawadee",
"Letter Gothic",
"Levenim MT",
"Lucida Bright",
"Lucida Sans",
"Menlo",
"MS Mincho",
"MS Outlook",
"MS Reference Specialty",
"MS UI Gothic",
"MT Extra",
"MYRIAD PRO",
"Marlett",
"Meiryo UI",
"Microsoft Uighur",
"Minion Pro",
"Monotype Corsiva",
"PMingLiU",
"Pristina",
"SCRIPTINA",
"Segoe UI Light",
"Serifa",
"SimHei",
"Small Fonts",
"Staccato222 BT",
"TRAJAN PRO",
"Univers CE 55 Medium",
"Vrinda",
"ZWAdobeF"
];
function getFonts() {
return withIframe(async (_, { document: document2 }) => {
const holder = document2.body;
holder.style.fontSize = textSize;
const spansContainer = document2.createElement("div");
spansContainer.style.setProperty("visibility", "hidden", "important");
const defaultWidth = {};
const defaultHeight = {};
const createSpan = (fontFamily) => {
const span = document2.createElement("span");
const { style } = span;
style.position = "absolute";
style.top = "0";
style.left = "0";
style.fontFamily = fontFamily;
span.textContent = testString;
spansContainer.appendChild(span);
return span;
};
const createSpanWithFonts = (fontToDetect, baseFont) => {
return createSpan(`'${fontToDetect}',${baseFont}`);
};
const initializeBaseFontsSpans = () => {
return baseFonts.map(createSpan);
};
const initializeFontsSpans = () => {
const spans = {};
for (const font of fontList) {
spans[font] = baseFonts.map((baseFont) => createSpanWithFonts(font, baseFont));
}
return spans;
};
const isFontAvailable = (fontSpans) => {
return baseFonts.some((baseFont, baseFontIndex) => fontSpans[baseFontIndex].offsetWidth !== defaultWidth[baseFont] || fontSpans[baseFontIndex].offsetHeight !== defaultHeight[baseFont]);
};
const baseFontsSpans = initializeBaseFontsSpans();
const fontsSpans = initializeFontsSpans();
holder.appendChild(spansContainer);
for (let index2 = 0; index2 < baseFonts.length; index2++) {
defaultWidth[baseFonts[index2]] = baseFontsSpans[index2].offsetWidth;
defaultHeight[baseFonts[index2]] = baseFontsSpans[index2].offsetHeight;
}
return fontList.filter((font) => isFontAvailable(fontsSpans[font]));
});
}
function getPlugins() {
const rawPlugins = navigator.plugins;
if (!rawPlugins) {
return void 0;
}
const plugins = [];
for (let i = 0; i < rawPlugins.length; ++i) {
const plugin = rawPlugins[i];
if (!plugin) {
continue;
}
const mimeTypes = [];
for (let j = 0; j < plugin.length; ++j) {
const mimeType = plugin[j];
mimeTypes.push({
type: mimeType.type,
suffixes: mimeType.suffixes
});
}
plugins.push({
name: plugin.name,
description: plugin.description,
mimeTypes
});
}
return plugins;
}
function getCanvasFingerprint() {
return getUnstableCanvasFingerprint(doesBrowserPerformAntifingerprinting());
}
function getUnstableCanvasFingerprint(skipImages) {
let winding = false;
let geometry;
let text;
const [canvas, context] = makeCanvasContext();
if (!isSupported(canvas, context)) {
geometry = text = "unsupported";
} else {
winding = doesSupportWinding(context);
if (skipImages) {
geometry = text = "skipped";
} else {
[geometry, text] = renderImages(canvas, context);
}
}
return { winding, geometry, text };
}
function makeCanvasContext() {
const canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
return [canvas, canvas.getContext("2d")];
}
function isSupported(canvas, context) {
return !!(context && canvas.toDataURL);
}
function doesSupportWinding(context) {
context.rect(0, 0, 10, 10);
context.rect(2, 2, 6, 6);
return !context.isPointInPath(5, 5, "evenodd");
}
function renderImages(canvas, context) {
renderTextImage(canvas, context);
const textImage1 = canvasToString(canvas);
const textImage2 = canvasToString(canvas);
if (textImage1 !== textImage2) {
return [
"unstable",
"unstable"
/* ImageStatus.Unstable */
];
}
renderGeometryImage(canvas, context);
const geometryImage = canvasToString(canvas);
return [geometryImage, textImage1];
}
function renderTextImage(canvas, context) {
canvas.width = 240;
canvas.height = 60;
context.textBaseline = "alphabetic";
context.fillStyle = "#f60";
context.fillRect(100, 1, 62, 20);
context.fillStyle = "#069";
context.font = '11pt "Times New Roman"';
const printedText = `Cwm fjordbank gly ${String.fromCharCode(55357, 56835)}`;
context.fillText(printedText, 2, 15);
context.fillStyle = "rgba(102, 204, 0, 0.2)";
context.font = "18pt Arial";
context.fillText(printedText, 4, 45);
}
function renderGeometryImage(canvas, context) {
canvas.width = 122;
canvas.height = 110;
context.globalCompositeOperation = "multiply";
for (const [color, x, y] of [
["#f2f", 40, 40],
["#2ff", 80, 40],
["#ff2", 60, 80]
]) {
context.fillStyle = color;
context.beginPath();
context.arc(x, y, 40, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}
context.fillStyle = "#f9c";
context.arc(60, 60, 60, 0, Math.PI * 2, true);
context.arc(60, 60, 20, 0, Math.PI * 2, true);
context.fill("evenodd");
}
function canvasToString(canvas) {
return canvas.toDataURL();
}
function doesBrowserPerformAntifingerprinting() {
return isWebKit() && isWebKit616OrNewer() && isSafariWebKit();
}
function getTouchSupport() {
const n = navigator;
let maxTouchPoints = 0;
let touchEvent;
if (n.maxTouchPoints !== void 0) {
maxTouchPoints = toInt(n.maxTouchPoints);
} else if (n.msMaxTouchPoints !== void 0) {
maxTouchPoints = n.msMaxTouchPoints;
}
try {
document.createEvent("TouchEvent");
touchEvent = true;
} catch (_a) {
touchEvent = false;
}
const touchStart = "ontouchstart" in window;
return {
maxTouchPoints,
touchEvent,
touchStart
};
}
function getOsCpu() {
return navigator.oscpu;
}
function getLanguages() {
const n = navigator;
const result = [];
const language = n.language || n.userLanguage || n.browserLanguage || n.systemLanguage;
if (language !== void 0) {
result.push([language]);
}
if (Array.isArray(n.languages)) {
if (!(isChromium() && isChromium86OrNewer())) {
result.push(n.languages);
}
} else if (typeof n.languages === "string") {
const languages = n.languages;
if (languages) {
result.push(languages.split(","));
}
}
return result;
}
function getColorDepth() {
return window.screen.colorDepth;
}
function getDeviceMemory() {
return replaceNaN(toFloat(navigator.deviceMemory), void 0);
}
function getScreenResolution() {
if (isWebKit() && isWebKit616OrNewer() && isSafariWebKit()) {
return void 0;
}
return getUnstableScreenResolution();
}
function getUnstableScreenResolution() {
const s = screen;
const parseDimension = (value) => replaceNaN(toInt(value), null);
const dimensions = [parseDimension(s.width), parseDimension(s.height)];
dimensions.sort().reverse();
return dimensions;
}
var screenFrameCheckInterval = 2500;
var roundingPrecision = 10;
var screenFrameBackup;
var screenFrameSizeTimeoutId;
function watchScreenFrame() {
if (screenFrameSizeTimeoutId !== void 0) {
return;
}
const checkScreenFrame = () => {
const frameSize = getCurrentScreenFrame();
if (isFrameSizeNull(frameSize)) {
screenFrameSizeTimeoutId = setTimeout(checkScreenFrame, screenFrameCheckInterval);
} else {
screenFrameBackup = frameSize;
screenFrameSizeTimeoutId = void 0;
}
};
checkScreenFrame();
}
function getUnstableScreenFrame() {
watchScreenFrame();
return async () => {
let frameSize = getCurrentScreenFrame();
if (isFrameSizeNull(frameSize)) {
if (screenFrameBackup) {
return [...screenFrameBackup];
}
if (getFullscreenElement()) {
await exitFullscreen();
frameSize = getCurrentScreenFrame();
}
}
if (!isFrameSizeNull(frameSize)) {
screenFrameBackup = frameSize;
}
return frameSize;
};
}
function getScreenFrame() {
if (isWebKit() && isWebKit616OrNewer() && isSafariWebKit()) {
return () => Promise.resolve(void 0);
}
const screenFrameGetter = getUnstableScreenFrame();
return async () => {
const frameSize = await screenFrameGetter();
const processSize = (sideSize) => sideSize === null ? null : round(sideSize, roundingPrecision);
return [processSize(frameSize[0]), processSize(frameSize[1]), processSize(frameSize[2]), processSize(frameSize[3])];
};
}
function getCurrentScreenFrame() {
const s = screen;
return [
replaceNaN(toFloat(s.availTop), null),
replaceNaN(toFloat(s.width) - toFloat(s.availWidth) - replaceNaN(toFloat(s.availLeft), 0), null),
replaceNaN(toFloat(s.height) - toFloat(s.availHeight) - replaceNaN(toFloat(s.availTop), 0), null),
replaceNaN(toFloat(s.availLeft), null)
];
}
function isFrameSizeNull(frameSize) {
for (let i = 0; i < 4; ++i) {
if (frameSize[i]) {
return false;
}
}
return true;
}
function getHardwareConcurrency() {
return replaceNaN(toInt(navigator.hardwareConcurrency), void 0);
}
function getTimezone() {
var _a;
const DateTimeFormat = (_a = window.Intl) === null || _a === void 0 ? void 0 : _a.DateTimeFormat;
if (DateTimeFormat) {
const timezone = new DateTimeFormat().resolvedOptions().timeZone;
if (timezone) {
return timezone;
}
}
const offset = -getTimezoneOffset();
return `UTC${offset >= 0 ? "+" : ""}${offset}`;
}
function getTimezoneOffset() {
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
return Math.max(
// `getTimezoneOffset` returns a number as a string in some unidentified cases
toFloat(new Date(currentYear, 0, 1).getTimezoneOffset()),
toFloat(new Date(currentYear, 6, 1).getTimezoneOffset())
);
}
function getSessionStorage() {
try {
return !!window.sessionStorage;
} catch (error) {
return true;
}
}
function getLocalStorage() {
try {
return !!window.localStorage;
} catch (e) {
return true;
}
}
function getIndexedDB() {
if (isTrident() || isEdgeHTML()) {
return void 0;
}
try {
return !!window.indexedDB;
} catch (e) {
return true;
}
}
function getOpenDatabase() {
return !!window.openDatabase;
}
function getCpuClass() {
return navigator.cpuClass;
}
function getPlatform() {
const { platform } = navigator;
if (platform === "MacIntel") {
if (isWebKit() && !isDesktopWebKit()) {
return isIPad() ? "iPad" : "iPhone";
}
}
return platform;
}
function getVendor() {
return navigator.vendor || "";
}
function getVendorFlavors() {
const flavors = [];
for (const key of [
// Blink and some browsers on iOS
"chrome",
// Safari on macOS
"safari",
// Chrome on iOS (checked in 85 on 13 and 87 on 14)
"__crWeb",
"__gCrWeb",
// Yandex Browser on iOS, macOS and Android (checked in 21.2 on iOS 14, macOS and Android)
"yandex",
// Yandex Browser on iOS (checked in 21.2 on 14)
"__yb",
"__ybro",
// Firefox on iOS (checked in 32 on 14)
"__firefox__",
// Edge on iOS (checked in 46 on 14)
"__edgeTrackingPreventionStatistics",
"webkit",
// Opera Touch on iOS (checked in 2.6 on 14)
"oprt",
// Samsung Internet on Android (checked in 11.1)
"samsungAr",
// UC Browser on Android (checked in 12.10 and 13.0)
"ucweb",
"UCShellJava",
// Puffin on Android (checked in 9.0)
"puffinDevice"
// UC on iOS and Opera on Android have no specific global variables
// Edge for Android isn't checked
]) {
const value = window[key];
if (value && typeof value === "object") {
flavors.push(key);
}
}
return flavors.sort();
}
function areCookiesEnabled() {
const d = document;
try {
d.cookie = "cookietest=1; SameSite=Strict;";
const result = d.cookie.indexOf("cookietest=") !== -1;
d.cookie = "cookietest=1; SameSite=Strict; expires=Thu, 01-Jan-1970 00:00:01 GMT";
return result;
} catch (e) {
return false;
}
}
function getFilters() {
const fromB64 = atob;
return {
abpIndo: [
"#Iklan-Melayang",
"#Kolom-Iklan-728",
"#SidebarIklan-wrapper",
'[title="ALIENBOLA" i]',
fromB64("I0JveC1CYW5uZXItYWRz")
],
abpvn: [".quangcao", "#mobileCatfish", fromB64("LmNsb3NlLWFkcw=="), '[id^="bn_bottom_fixed_"]', "#pmadv"],
adBlockFinland: [
".mainostila",
fromB64("LnNwb25zb3JpdA=="),
".ylamainos",
fromB64("YVtocmVmKj0iL2NsaWNrdGhyZ2guYXNwPyJd"),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9hcHAucmVhZHBlYWsuY29tL2FkcyJd")
],
adBlockPersian: [
"#navbar_notice_50",
".kadr",
'TABLE[width="140px"]',
"#divAgahi",
fromB64("YVtocmVmXj0iaHR0cDovL2cxLnYuZndtcm0ubmV0L2FkLyJd")
],
adBlockWarningRemoval: [
"#adblock-honeypot",
".adblocker-root",
".wp_adblock_detect",
fromB64("LmhlYWRlci1ibG9ja2VkLWFk"),
fromB64("I2FkX2Jsb2NrZXI=")
],
adGuardAnnoyances: [
".hs-sosyal",
"#cookieconsentdiv",
'div[class^="app_gdpr"]',
".as-oil",
'[data-cypress="soft-push-notification-modal"]'
],
adGuardBase: [
".BetterJsPopOverlay",
fromB64("I2FkXzMwMFgyNTA="),
fromB64("I2Jhbm5lcmZsb2F0MjI="),
fromB64("I2NhbXBhaWduLWJhbm5lcg=="),
fromB64("I0FkLUNvbnRlbnQ=")
],
adGuardChinese: [
fromB64("LlppX2FkX2FfSA=="),
fromB64("YVtocmVmKj0iLmh0aGJldDM0LmNvbSJd"),
"#widget-quan",
fromB64("YVtocmVmKj0iLzg0OTkyMDIwLnh5eiJd"),
fromB64("YVtocmVmKj0iLjE5NTZobC5jb20vIl0=")
],
adGuardFrench: [
"#pavePub",
fromB64("LmFkLWRlc2t0b3AtcmVjdGFuZ2xl"),
".mobile_adhesion",
".widgetadv",
fromB64("LmFkc19iYW4=")
],
adGuardGerman: ['aside[data-portal-id="leaderboard"]'],
adGuardJapanese: [
"#kauli_yad_1",
fromB64("YVtocmVmXj0iaHR0cDovL2FkMi50cmFmZmljZ2F0ZS5uZXQvIl0="),
fromB64("Ll9wb3BJbl9pbmZpbml0ZV9hZA=="),
fromB64("LmFkZ29vZ2xl"),
fromB64("Ll9faXNib29zdFJldHVybkFk")
],
adGuardMobile: [
fromB64("YW1wLWF1dG8tYWRz"),
fromB64("LmFtcF9hZA=="),
'amp-embed[type="24smi"]',
"#mgid_iframe1",
fromB64("I2FkX2ludmlld19hcmVh")
],
adGuardRussian: [
fromB64("YVtocmVmXj0iaHR0cHM6Ly9hZC5sZXRtZWFkcy5jb20vIl0="),
fromB64("LnJlY2xhbWE="),
'div[id^="smi2adblock"]',
fromB64("ZGl2W2lkXj0iQWRGb3hfYmFubmVyXyJd"),
"#psyduckpockeball"
],
adGuardSocial: [
fromB64("YVtocmVmXj0iLy93d3cuc3R1bWJsZXVwb24uY29tL3N1Ym1pdD91cmw9Il0="),
fromB64("YVtocmVmXj0iLy90ZWxlZ3JhbS5tZS9zaGFyZS91cmw/Il0="),
".etsy-tweet",
"#inlineShare",
".popup-social"
],
adGuardSpanishPortuguese: ["#barraPublicidade", "#Publicidade", "#publiEspecial", "#queTooltip", ".cnt-publi"],
adGuardTrackingProtection: [
"#qoo-counter",
fromB64("YVtocmVmXj0iaHR0cDovL2NsaWNrLmhvdGxvZy5ydS8iXQ=="),
fromB64("YVtocmVmXj0iaHR0cDovL2hpdGNvdW50ZXIucnUvdG9wL3N0YXQucGhwIl0="),
fromB64("YVtocmVmXj0iaHR0cDovL3RvcC5tYWlsLnJ1L2p1bXAiXQ=="),
"#top100counter"
],
adGuardTurkish: [
"#backkapat",
fromB64("I3Jla2xhbWk="),
fromB64("YVtocmVmXj0iaHR0cDovL2Fkc2Vydi5vbnRlay5jb20udHIvIl0="),
fromB64("YVtocmVmXj0iaHR0cDovL2l6bGVuemkuY29tL2NhbXBhaWduLyJd"),
fromB64("YVtocmVmXj0iaHR0cDovL3d3dy5pbnN0YWxsYWRzLm5ldC8iXQ==")
],
bulgarian: [fromB64("dGQjZnJlZW5ldF90YWJsZV9hZHM="), "#ea_intext_div", ".lapni-pop-over", "#xenium_hot_offers"],
easyList: [
".yb-floorad",
fromB64("LndpZGdldF9wb19hZHNfd2lkZ2V0"),
fromB64("LnRyYWZmaWNqdW5reS1hZA=="),
".textad_headline",
fromB64("LnNwb25zb3JlZC10ZXh0LWxpbmtz")
],
easyListChina: [
fromB64("LmFwcGd1aWRlLXdyYXBbb25jbGljayo9ImJjZWJvcy5jb20iXQ=="),
fromB64("LmZyb250cGFnZUFkdk0="),
"#taotaole",
"#aafoot.top_box",
".cfa_popup"
],
easyListCookie: [
".ezmob-footer",
".cc-CookieWarning",
"[data-cookie-number]",
fromB64("LmF3LWNvb2tpZS1iYW5uZXI="),
".sygnal24-gdpr-modal-wrap"
],
easyListCzechSlovak: [
"#onlajny-stickers",
fromB64("I3Jla2xhbW5pLWJveA=="),
fromB64("LnJla2xhbWEtbWVnYWJvYXJk"),
".sklik",
fromB64("W2lkXj0ic2tsaWtSZWtsYW1hIl0=")
],
easyListDutch: [
fromB64("I2FkdmVydGVudGll"),
fromB64("I3ZpcEFkbWFya3RCYW5uZXJCbG9jaw=="),
".adstekst",
fromB64("YVtocmVmXj0iaHR0cHM6Ly94bHR1YmUubmwvY2xpY2svIl0="),
"#semilo-lrectangle"
],
easyListGermany: [
"#SSpotIMPopSlider",
fromB64("LnNwb25zb3JsaW5rZ3J1ZW4="),
fromB64("I3dlcmJ1bmdza3k="),
fromB64("I3Jla2xhbWUtcmVjaHRzLW1pdHRl"),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9iZDc0Mi5jb20vIl0=")
],
easyListItaly: [
fromB64("LmJveF9hZHZfYW5udW5jaQ=="),
".sb-box-pubbliredazionale",
fromB64("YVtocmVmXj0iaHR0cDovL2FmZmlsaWF6aW9uaWFkcy5zbmFpLml0LyJd"),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9hZHNlcnZlci5odG1sLml0LyJd"),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9hZmZpbGlhemlvbmlhZHMuc25haS5pdC8iXQ==")
],
easyListLithuania: [
fromB64("LnJla2xhbW9zX3RhcnBhcw=="),
fromB64("LnJla2xhbW9zX251b3JvZG9z"),
fromB64("aW1nW2FsdD0iUmVrbGFtaW5pcyBza3lkZWxpcyJd"),
fromB64("aW1nW2FsdD0iRGVkaWt1b3RpLmx0IHNlcnZlcmlhaSJd"),
fromB64("aW1nW2FsdD0iSG9zdGluZ2FzIFNlcnZlcmlhaS5sdCJd")
],
estonian: [fromB64("QVtocmVmKj0iaHR0cDovL3BheTRyZXN1bHRzMjQuZXUiXQ==")],
fanboyAnnoyances: ["#ac-lre-player", ".navigate-to-top", "#subscribe_popup", ".newsletter_holder", "#back-top"],
fanboyAntiFacebook: [".util-bar-module-firefly-visible"],
fanboyEnhancedTrackers: [
".open.pushModal",
"#issuem-leaky-paywall-articles-zero-remaining-nag",
"#sovrn_container",
'div[class$="-hide"][zoompage-fontsize][style="display: block;"]',
".BlockNag__Card"
],
fanboySocial: ["#FollowUs", "#meteored_share", "#social_follow", ".article-sharer", ".community__social-desc"],
frellwitSwedish: [
fromB64("YVtocmVmKj0iY2FzaW5vcHJvLnNlIl1bdGFyZ2V0PSJfYmxhbmsiXQ=="),
fromB64("YVtocmVmKj0iZG9rdG9yLXNlLm9uZWxpbmsubWUiXQ=="),
"article.category-samarbete",
fromB64("ZGl2LmhvbGlkQWRz"),
"ul.adsmodern"
],
greekAdBlock: [
fromB64("QVtocmVmKj0iYWRtYW4ub3RlbmV0LmdyL2NsaWNrPyJd"),
fromB64("QVtocmVmKj0iaHR0cDovL2F4aWFiYW5uZXJzLmV4b2R1cy5nci8iXQ=="),
fromB64("QVtocmVmKj0iaHR0cDovL2ludGVyYWN0aXZlLmZvcnRobmV0LmdyL2NsaWNrPyJd"),
"DIV.agores300",
"TABLE.advright"
],
hungarian: [
"#cemp_doboz",
".optimonk-iframe-container",
fromB64("LmFkX19tYWlu"),
fromB64("W2NsYXNzKj0iR29vZ2xlQWRzIl0="),
"#hirdetesek_box"
],
iDontCareAboutCookies: [
'.alert-info[data-block-track*="CookieNotice"]',
".ModuleTemplateCookieIndicator",
".o--cookies--container",
"#cookies-policy-sticky",
"#stickyCookieBar"
],
icelandicAbp: [fromB64("QVtocmVmXj0iL2ZyYW1ld29yay9yZXNvdXJjZXMvZm9ybXMvYWRzLmFzcHgiXQ==")],
latvian: [
fromB64("YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiAxMjBweDsgaGVpZ2h0OiA0MHB4OyBvdmVyZmxvdzogaGlkZGVuOyBwb3NpdGlvbjogcmVsYXRpdmU7Il0="),
fromB64("YVtocmVmPSJodHRwOi8vd3d3LnNhbGlkemluaS5sdi8iXVtzdHlsZT0iZGlzcGxheTogYmxvY2s7IHdpZHRoOiA4OHB4OyBoZWlnaHQ6IDMxcHg7IG92ZXJmbG93OiBoaWRkZW47IHBvc2l0aW9uOiByZWxhdGl2ZTsiXQ==")
],
listKr: [
fromB64("YVtocmVmKj0iLy9hZC5wbGFuYnBsdXMuY28ua3IvIl0="),
fromB64("I2xpdmVyZUFkV3JhcHBlcg=="),
fromB64("YVtocmVmKj0iLy9hZHYuaW1hZHJlcC5jby5rci8iXQ=="),
fromB64("aW5zLmZhc3R2aWV3LWFk"),
".revenue_unit_item.dable"
],
listeAr: [
fromB64("LmdlbWluaUxCMUFk"),
".right-and-left-sponsers",
fromB64("YVtocmVmKj0iLmFmbGFtLmluZm8iXQ=="),
fromB64("YVtocmVmKj0iYm9vcmFxLm9yZyJd"),
fromB64("YVtocmVmKj0iZHViaXp6bGUuY29tL2FyLz91dG1fc291cmNlPSJd")
],
listeFr: [
fromB64("YVtocmVmXj0iaHR0cDovL3Byb21vLnZhZG9yLmNvbS8iXQ=="),
fromB64("I2FkY29udGFpbmVyX3JlY2hlcmNoZQ=="),
fromB64("YVtocmVmKj0id2Vib3JhbWEuZnIvZmNnaS1iaW4vIl0="),
".site-pub-interstitiel",
'div[id^="crt-"][data-criteo-id]'
],
officialPolish: [
"#ceneo-placeholder-ceneo-12",
fromB64("W2hyZWZePSJodHRwczovL2FmZi5zZW5kaHViLnBsLyJd"),
fromB64("YVtocmVmXj0iaHR0cDovL2Fkdm1hbmFnZXIudGVjaGZ1bi5wbC9yZWRpcmVjdC8iXQ=="),
fromB64("YVtocmVmXj0iaHR0cDovL3d3dy50cml6ZXIucGwvP3V0bV9zb3VyY2UiXQ=="),
fromB64("ZGl2I3NrYXBpZWNfYWQ=")
],
ro: [
fromB64("YVtocmVmXj0iLy9hZmZ0cmsuYWx0ZXgucm8vQ291bnRlci9DbGljayJd"),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9ibGFja2ZyaWRheXNhbGVzLnJvL3Ryay9zaG9wLyJd"),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9ldmVudC4ycGVyZm9ybWFudC5jb20vZXZlbnRzL2NsaWNrIl0="),
fromB64("YVtocmVmXj0iaHR0cHM6Ly9sLnByb2ZpdHNoYXJlLnJvLyJd"),
'a[href^="/url/"]'
],
ruAd: [
fromB64("YVtocmVmKj0iLy9mZWJyYXJlLnJ1LyJd"),
fromB64("YVtocmVmKj0iLy91dGltZy5ydS8iXQ=="),
fromB64("YVtocmVmKj0iOi8vY2hpa2lkaWtpLnJ1Il0="),
"#pgeldiz",
".yandex-rtb-block"
],
thaiAds: [
"a[href*=macau-uta-popup]",
fromB64("I2Fkcy1nb29nbGUtbWlkZGxlX3JlY3RhbmdsZS1ncm91cA=="),
fromB64("LmFkczMwMHM="),
".bumq",
".img-kosana"
],
webAnnoyancesUltralist: [
"#mod-social-share-2",
"#social-tools",
fromB64("LmN0cGwtZnVsbGJhbm5lcg=="),
".zergnet-recommend",
".yt.btn-link.btn-md.btn"
]
};
}
async function getDomBlockers({ debug } = {}) {
if (!isApplicable()) {
return void 0;
}
const filters = getFilters();
const filterNames = Object.keys(filters);
const allSelectors = [].concat(...filterNames.map((filterName) => filters[filterName]));
const blockedSelectors = await getBlockedSelectors(allSelectors);
if (debug) {
printDebug(filters, blockedSelectors);
}
const activeBlockers = filterNames.filter((filterName) => {
const selectors = filters[filterName];
const blockedCount = countTruthy(selectors.map((selector) => blockedSelectors[selector]));
return blockedCount > selectors.length * 0.6;
});
activeBlockers.sort();
return activeBlockers;
}
function isApplicable() {
return isWebKit() || isAndroid();
}
async function getBlockedSelectors(selectors) {
var _a;
const d = document;
const root = d.createElement("div");
const elements = new Array(selectors.length);
const blockedSelectors = {};
forceShow(root);
for (let i = 0; i < selectors.length; ++i) {
const element = selectorToElement(selectors[i]);
if (element.tagName === "DIALOG") {
element.show();
}
const holder = d.createElement("div");
forceShow(holder);
holder.appendChild(element);
root.appendChild(holder);
elements[i] = element;
}
while (!d.body) {
await wait(50);
}
d.body.appendChild(root);
try {
for (let i = 0; i < selectors.length; ++i) {
if (!elements[i].offsetParent) {
blockedSelectors[selectors[i]] = true;
}
}
} finally {
(_a = root.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(root);
}
return blockedSelectors;
}
function forceShow(element) {
element.style.setProperty("visibility", "hidden", "important");
element.style.setProperty("display", "block", "important");
}
function printDebug(filters, blockedSelectors) {
let message = "DOM blockers debug:\n```";
for (const filterName of Object.keys(filters)) {
message += `
${filterName}:`;
for (const selector of filters[filterName]) {
message += `
${blockedSelectors[selector] ? "\u{1F6AB}" : "\u27A1\uFE0F"} ${selector}`;
}
}
console.log(`${message}
\`\`\``);
}
function getColorGamut() {
for (const gamut of ["rec2020", "p3", "srgb"]) {
if (matchMedia(`(color-gamut: ${gamut})`).matches) {
return gamut;
}
}
return void 0;
}
function areColorsInverted() {
if (doesMatch$5("inverted")) {
return true;
}
if (doesMatch$5("none")) {
return false;
}
return void 0;
}
function doesMatch$5(value) {
return matchMedia(`(inverted-colors: ${value})`).matches;
}
function areColorsForced() {
if (doesMatch$4("active")) {
return true;
}
if (doesMatch$4("none")) {
return false;
}
return void 0;
}
function doesMatch$4(value) {
return matchMedia(`(forced-colors: ${value})`).matches;
}
var maxValueToCheck = 100;
function getMonochromeDepth() {
if (!matchMedia("(min-monochrome: 0)").matches) {
return void 0;
}
for (let i = 0; i <= maxValueToCheck; ++i) {
if (matchMedia(`(max-monochrome: ${i})`).matches) {
return i;
}
}
throw new Error("Too high value");
}
function getContrastPreference() {
if (doesMatch$3("no-preference")) {
return 0;
}
if (doesMatch$3("high") || doesMatch$3("more")) {
return 1;
}
if (doesMatch$3("low") || doesMatch$3("less")) {
return -1;
}
if (doesMatch$3("forced")) {
return 10;
}
return void 0;
}
function doesMatch$3(value) {
return matchMedia(`(prefers-contrast: ${value})`).matches;
}
function isMotionReduced() {
if (doesMatch$2("reduce")) {
return true;
}
if (doesMatch$2("no-preference")) {
return false;
}
return void 0;
}
function doesMatch$2(value) {
return matchMedia(`(prefers-reduced-motion: ${value})`).matches;
}
function isTransparencyReduced() {
if (doesMatch$1("reduce")) {
return true;
}
if (doesMatch$1("no-preference")) {
return false;
}
return void 0;
}
function doesMatch$1(value) {
return matchMedia(`(prefers-reduced-transparency: ${value})`).matches;
}
function isHDR() {
if (doesMatch("high")) {
return true;
}
if (doesMatch("standard")) {
return false;
}
return void 0;
}
function doesMatch(value) {
return matchMedia(`(dynamic-range: ${value})`).matches;
}
var M = Math;
var fallbackFn = () => 0;
function getMathFingerprint() {
const acos = M.acos || fallbackFn;
const acosh = M.acosh || fallbackFn;
const asin = M.asin || fallbackFn;
const asinh = M.asinh || fallbackFn;
const atanh = M.atanh || fallbackFn;
const atan = M.atan || fallbackFn;
const sin = M.sin || fallbackFn;
const sinh = M.sinh || fallbackFn;
const cos = M.cos || fallbackFn;
const cosh = M.cosh || fallbackFn;
const tan = M.tan || fallbackFn;
const tanh = M.tanh || fallbackFn;
const exp = M.exp || fallbackFn;
const expm1 = M.expm1 || fallbackFn;
const log1p = M.log1p || fallbackFn;
const powPI = (value) => M.pow(M.PI, value);
const acoshPf = (value) => M.log(value + M.sqrt(value * value - 1));
const asinhPf = (value) => M.log(value + M.sqrt(value * value + 1));
const atanhPf = (value) => M.log((1 + value) / (1 - value)) / 2;
const sinhPf = (value) => M.exp(value) - 1 / M.exp(value) / 2;
const coshPf = (value) => (M.exp(value) + 1 / M.exp(value)) / 2;
const expm1Pf = (value) => M.exp(value) - 1;
const tanhPf = (value) => (M.exp(2 * value) - 1) / (M.exp(2 * value) + 1);
const log1pPf = (value) => M.log(1 + value);
return {
acos: acos(0.12312423423423424),
acosh: acosh(1e308),
acoshPf: acoshPf(1e154),
asin: asin(0.12312423423423424),
asinh: asinh(1),
asinhPf: asinhPf(1),
atanh: atanh(0.5),
atanhPf: atanhPf(0.5),
atan: atan(0.5),
sin: sin(-1e300),
sinh: sinh(1),
sinhPf: sinhPf(1),
cos: cos(10.000000000123),
cosh: cosh(1),
coshPf: coshPf(1),
tan: tan(-1e300),
tanh: tanh(1),
tanhPf: tanhPf(1),
exp: exp(1),
expm1: expm1(1),
expm1Pf: expm1Pf(1),
log1p: log1p(10),
log1pPf: log1pPf(10),
powPI: powPI(-100)
};
}
var defaultText = "mmMwWLliI0fiflO&1";
var presets = {
/**
* The default font. User can change it in desktop Chrome, desktop Firefox, IE 11,
* Android Chrome (but only when the size is ≥ than the default) and Android Firefox.
*/
default: [],
/** OS font on macOS. User can change its size and weight. Applies after Safari restart. */
apple: [{ font: "-apple-system-body" }],
/** User can change it in desktop Chrome and desktop Firefox. */
serif: [{ fontFamily: "serif" }],
/** User can change it in desktop Chrome and desktop Firefox. */
sans: [{ fontFamily: "sans-serif" }],
/** User can change it in desktop Chrome and desktop Firefox. */
mono: [{ fontFamily: "monospace" }],
/**
* Check the smallest allowed font size. User can change it in desktop Chrome, desktop Firefox and desktop Safari.
* The height can be 0 in Chrome on a retina display.
*/
min: [{ fontSize: "1px" }],
/** Tells one OS from another in desktop Chrome. */
system: [{ fontFamily: "system-ui" }]
};
function getFontPreferences() {
return withNaturalFonts((document2, container) => {
const elements = {};
const sizes = {};
for (const key of Object.keys(presets)) {
const [style = {}, text = defaultText] = presets[key];
const element = document2.createElement("span");
element.textContent = text;
element.style.whiteSpace = "nowrap";
for (const name6 of Object.keys(style)) {
const value = style[name6];
if (value !== void 0) {
element.style[name6] = value;
}
}
elements[key] = element;
container.append(document2.createElement("br"), element);
}
for (const key of Object.keys(presets)) {
sizes[key] = elements[key].getBoundingClientRect().width;
}
return sizes;
});
}
function withNaturalFonts(action, containerWidthPx = 4e3) {
return withIframe((_, iframeWindow) => {
const iframeDocument = iframeWindow.document;
const iframeBody = iframeDocument.body;
const bodyStyle = iframeBody.style;
bodyStyle.width = `${containerWidthPx}px`;
bodyStyle.webkitTextSizeAdjust = bodyStyle.textSizeAdjust = "none";
if (isChromium()) {
iframeBody.style.zoom = `${1 / iframeWindow.devicePixelRatio}`;
} else if (isWebKit()) {
iframeBody.style.zoom = "reset";
}
const linesOfText = iframeDocument.createElement("div");
linesOfText.textContent = [...Array(containerWidthPx / 20 << 0)].map(() => "word").join(" ");
iframeBody.appendChild(linesOfText);
return action(iframeDocument, iframeBody);
}, '<!doctype html><html><head><meta name="viewport" content="width=device-width, initial-scale=1">');
}
function isPdfViewerEnabled() {
return navigator.pdfViewerEnabled;
}
function getArchitecture() {
const f = new Float32Array(1);
const u8 = new Uint8Array(f.buffer);
f[0] = Infinity;
f[0] = f[0] - f[0];
return u8[3];
}
function getApplePayState() {
const { ApplePaySession } = window;
if (typeof (ApplePaySession === null || ApplePaySession === void 0 ? void 0 : ApplePaySession.canMakePayments) !== "function") {
return -1;
}
if (willPrintConsoleError()) {
return -3;
}
try {
return ApplePaySession.canMakePayments() ? 1 : 0;
} catch (error) {
return getStateFromError(error);
}
}
var willPrintConsoleError = isAnyParentCrossOrigin;
function getStateFromError(error) {
if (error instanceof Error && error.name === "InvalidAccessError" && /\bfrom\b.*\binsecure\b/i.test(error.message)) {
return -2;
}
throw error;
}
function getPrivateClickMeasurement() {
var _a;
const link = document.createElement("a");
const sourceId = (_a = link.attributionSourceId) !== null && _a !== void 0 ? _a : link.attributionsourceid;
return sourceId === void 0 ? void 0 : String(sourceId);
}
var STATUS_NO_GL_CONTEXT = -1;
var STATUS_GET_PARAMETER_NOT_A_FUNCTION = -2;
var validContextParameters = /* @__PURE__ */ new Set([
10752,
2849,
2884,
2885,
2886,
2928,
2929,
2930,
2931,
2932,
2960,
2961,
2962,
2963,
2964,
2965,
2966,
2967,
2968,
2978,
3024,
3042,
3088,
3089,
3106,
3107,
32773,
32777,
32777,
32823,
32824,
32936,
32937,
32938,
32939,
32968,
32969,
32970,
32971,
3317,
33170,
3333,
3379,
3386,
33901,
33902,
34016,
34024,
34076,
3408,
3410,
3411,
3412,
3413,
3414,
3415,
34467,
34816,
34817,
34818,
34819,
34877,
34921,
34930,
35660,
35661,
35724,
35738,
35739,
36003,
36004,
36005,
36347,
36348,
36349,
37440,
37441,
37443,
7936,
7937,
7938
// SAMPLE_ALPHA_TO_COVERAGE (32926) and SAMPLE_COVERAGE (32928) are excluded because they trigger a console warning
// in IE, Chrome ≤ 59 and Safari ≤ 13 and give no entropy.
]);
var validExtensionParams = /* @__PURE__ */ new Set([
34047,
35723,
36063,
34852,
34853,
34854,
34229,
36392,
36795,
38449
// MAX_VIEWS_OVR
]);
var shaderTypes = ["FRAGMENT_SHADER", "VERTEX_SHADER"];
var precisionTypes = ["LOW_FLOAT", "MEDIUM_FLOAT", "HIGH_FLOAT", "LOW_INT", "MEDIUM_INT", "HIGH_INT"];
var rendererInfoExtensionName = "WEBGL_debug_renderer_info";
var polygonModeExtensionName = "WEBGL_polygon_mode";
function getWebGlBasics({ cache }) {
var _a, _b, _c, _d, _e, _f;
const gl = getWebGLContext(cache);
if (!gl) {
return STATUS_NO_GL_CONTEXT;
}
if (!isValidParameterGetter(gl)) {
return STATUS_GET_PARAMETER_NOT_A_FUNCTION;
}
const debugExtension = shouldAvoidDebugRendererInfo() ? null : gl.getExtension(rendererInfoExtensionName);
return {
version: ((_a = gl.getParameter(gl.VERSION)) === null || _a === void 0 ? void 0 : _a.toString()) || "",
vendor: ((_b = gl.getParameter(gl.VENDOR)) === null || _b === void 0 ? void 0 : _b.toString()) || "",
vendorUnmasked: debugExtension ? (_c = gl.getParameter(debugExtension.UNMASKED_VENDOR_WEBGL)) === null || _c === void 0 ? void 0 : _c.toString() : "",
renderer: ((_d = gl.getParameter(gl.RENDERER)) === null || _d === void 0 ? void 0 : _d.toString()) || "",
rendererUnmasked: debugExtension ? (_e = gl.getParameter(debugExtension.UNMASKED_RENDERER_WEBGL)) === null || _e === void 0 ? void 0 : _e.toString() : "",
shadingLanguageVersion: ((_f = gl.getParameter(gl.SHADING_LANGUAGE_VERSION)) === null || _f === void 0 ? void 0 : _f.toString()) || ""
};
}
function getWebGlExtensions({ cache }) {
const gl = getWebGLContext(cache);
if (!gl) {
return STATUS_NO_GL_CONTEXT;
}
if (!isValidParameterGetter(gl)) {
return STATUS_GET_PARAMETER_NOT_A_FUNCTION;
}
const extensions = gl.getSupportedExtensions();
const contextAttributes = gl.getContextAttributes();
const unsupportedExtensions = [];
const attributes = [];
const parameters = [];
const extensionParameters = [];
const shaderPrecisions = [];
if (contextAttributes) {
for (const attributeName of Object.keys(contextAttributes)) {
attributes.push(`${attributeName}=${contextAttributes[attributeName]}`);
}
}
const constants = getConstantsFromPrototype(gl);
for (const constant of constants) {
const code = gl[constant];
parameters.push(`${constant}=${code}${validContextParameters.has(code) ? `=${gl.getParameter(code)}` : ""}`);
}
if (extensions) {
for (const name6 of extensions) {
if (name6 === rendererInfoExtensionName && shouldAvoidDebugRendererInfo() || name6 === polygonModeExtensionName && shouldAvoidPolygonModeExtensions()) {
continue;
}
const extension = gl.getExtension(name6);
if (!extension) {
unsupportedExtensions.push(name6);
continue;
}
for (const constant of getConstantsFromPrototype(extension)) {
const code = extension[constant];
extensionParameters.push(`${constant}=${code}${validExtensionParams.has(code) ? `=${gl.getParameter(code)}` : ""}`);
}
}
}
for (const shaderType of shaderTypes) {
for (const precisionType of precisionTypes) {
const shaderPrecision = getShaderPrecision(gl, shaderType, precisionType);
shaderPrecisions.push(`${shaderType}.${precisionType}=${shaderPrecision.join(",")}`);
}
}
extensionParameters.sort();
parameters.sort();
return {
contextAttributes: attributes,
parameters,
shaderPrecisions,
extensions,
extensionParameters,
unsupportedExtensions
};
}
function getWebGLContext(cache) {
if (cache.webgl) {
return cache.webgl.context;
}
const canvas = document.createElement("canvas");
let context;
canvas.addEventListener("webglCreateContextError", () => context = void 0);
for (const type of ["webgl", "experimental-webgl"]) {
try {
context = canvas.getContext(type);
} catch (_a) {
}
if (context) {
break;
}
}
cache.webgl = { context };
return context;
}
function getShaderPrecision(gl, shaderType, precisionType) {
const shaderPrecision = gl.getShaderPrecisionFormat(gl[shaderType], gl[precisionType]);
return shaderPrecision ? [shaderPrecision.rangeMin, shaderPrecision.rangeMax, shaderPrecision.precision] : [];
}
function getConstantsFromPrototype(obj) {
const keys = Object.keys(obj.__proto__);
return keys.filter(isConstantLike);
}
function isConstantLike(key) {
return typeof key === "string" && !key.match(/[^A-Z0-9_x]/);
}
function shouldAvoidDebugRendererInfo() {
return isGecko();
}
function shouldAvoidPolygonModeExtensions() {
return isChromium() || isWebKit();
}
function isValidParameterGetter(gl) {
return typeof gl.getParameter === "function";
}
function getAudioContextBaseLatency() {
const isAllowedPlatform = isAndroid() || isWebKit();
if (!isAllowedPlatform) {
return -2;
}
if (!window.AudioContext) {
return -1;
}
const latency = new AudioContext().baseLatency;
if (latency === null || latency === void 0) {
return -1;
}
if (!isFinite(latency)) {
return -3;
}
return latency;
}
function getDateTimeLocale() {
if (!window.Intl) {
return -1;
}
const DateTimeFormat = window.Intl.DateTimeFormat;
if (!DateTimeFormat) {
return -2;
}
const locale = DateTimeFormat().resolvedOptions().locale;
if (!locale && locale !== "") {
return -3;
}
return locale;
}
var sources = {
// READ FIRST:
// See https://github.com/fingerprintjs/fingerprintjs/blob/master/contributing.md#how-to-add-an-entropy-source
// to learn how entropy source works and how to make your own.
// The sources run in this exact order.
// The asynchronous sources are at the start to run in parallel with other sources.
fonts: getFonts,
domBlockers: getDomBlockers,
fontPreferences: getFontPreferences,
audio: getAudioFingerprint,
screenFrame: getScreenFrame,
canvas: getCanvasFingerprint,
osCpu: getOsCpu,
languages: getLanguages,
colorDepth: getColorDepth,
deviceMemory: getDeviceMemory,
screenResolution: getScreenResolution,
hardwareConcurrency: getHardwareConcurrency,
timezone: getTimezone,
sessionStorage: getSessionStorage,
localStorage: getLocalStorage,
indexedDB: getIndexedDB,
openDatabase: getOpenDatabase,
cpuClass: getCpuClass,
platform: getPlatform,
plugins: getPlugins,
touchSupport: getTouchSupport,
vendor: getVendor,
vendorFlavors: getVendorFlavors,
cookiesEnabled: areCookiesEnabled,
colorGamut: getColorGamut,
invertedColors: areColorsInverted,
forcedColors: areColorsForced,
monochrome: getMonochromeDepth,
contrast: getContrastPreference,
reducedMotion: isMotionReduced,
reducedTransparency: isTransparencyReduced,
hdr: isHDR,
math: getMathFingerprint,
pdfViewerEnabled: isPdfViewerEnabled,
architecture: getArchitecture,
applePay: getApplePayState,
privateClickMeasurement: getPrivateClickMeasurement,
audioBaseLatency: getAudioContextBaseLatency,
dateTimeLocale: getDateTimeLocale,
// Some sources can affect other sources (e.g. WebGL can affect canvas), so it's important to run these sources
// after other sources.
webGlBasics: getWebGlBasics,
webGlExtensions: getWebGlExtensions
};
function loadBuiltinSources(options) {
return loadSources(sources, options, []);
}
var commentTemplate = "$ if upgrade to Pro: https://fpjs.dev/pro";
function getConfidence(components) {
const openConfidenceScore = getOpenConfidenceScore(components);
const proConfidenceScore = deriveProConfidenceScore(openConfidenceScore);
return { score: openConfidenceScore, comment: commentTemplate.replace(/\$/g, `${proConfidenceScore}`) };
}
function getOpenConfidenceScore(components) {
if (isAndroid()) {
return 0.4;
}
if (isWebKit()) {
return isDesktopWebKit() && !(isWebKit616OrNewer() && isSafariWebKit()) ? 0.5 : 0.3;
}
const platform = "value" in components.platform ? components.platform.value : "";
if (/^Win/.test(platform)) {
return 0.6;
}
if (/^Mac/.test(platform)) {
return 0.5;
}
return 0.7;
}
function deriveProConfidenceScore(openConfidenceScore) {
return round(0.99 + 0.01 * openConfidenceScore, 1e-4);
}
function componentsToCanonicalString(components) {
let result = "";
for (const componentKey of Object.keys(components).sort()) {
const component = components[componentKey];
const value = "error" in component ? "error" : JSON.stringify(component.value);
result += `${result ? "|" : ""}${componentKey.replace(/([:|\\])/g, "\\$1")}:${value}`;
}
return result;
}
function componentsToDebugString(components) {
return JSON.stringify(components, (_key, value) => {
if (value instanceof Error) {
return errorToObject(value);
}
return value;
}, 2);
}
function hashComponents(components) {
return x64hash128(componentsToCanonicalString(components));
}
function makeLazyGetResult(components) {
let visitorIdCache;
const confidence = getConfidence(components);
return {
get visitorId() {
if (visitorIdCache === void 0) {
visitorIdCache = hashComponents(this.components);
}
return visitorIdCache;
},
set visitorId(visitorId) {
visitorIdCache = visitorId;
},
confidence,
components,
version: version6
};
}
function prepareForSources(delayFallback = 50) {
return requestIdleCallbackIfAvailable(delayFallback, delayFallback * 2);
}
function makeAgent(getComponents, debug) {
const creationTime = Date.now();
return {
async get(options) {
const startTime = Date.now();
const components = await getComponents();
const result = makeLazyGetResult(components);
if (debug || (options === null || options === void 0 ? void 0 : options.debug)) {
console.log(`Copy the text below to get the debug data:
\`\`\`
version: ${result.version}
userAgent: ${navigator.userAgent}
timeBetweenLoadAndGet: ${startTime - creationTime}
visitorId: ${result.visitorId}
components: ${componentsToDebugString(components)}
\`\`\``);
}
return result;
}
};
}
function monitor() {
if (window.__fpjs_d_m || Math.random() >= 1e-3) {
return;
}
try {
const request = new XMLHttpRequest();
request.open("get", `https://m1.openfpcdn.io/fingerprintjs/v${version6}/npm-monitoring`, true);
request.send();
} catch (error) {
console.error(error);
}
}
async function load(options = {}) {
var _a;
if ((_a = options.monitoring) !== null && _a !== void 0 ? _a : true) {
monitor();
}
const { delayFallback, debug } = options;
await prepareForSources(delayFallback);
const getComponents = loadBuiltinSources({ cache: {}, debug });
return makeAgent(getComponents, debug);
}
var index = { load, hashComponents, componentsToDebugString };
var murmurX64Hash128 = x64hash128;
exports2.componentsToDebugString = componentsToDebugString;
exports2.default = index;
exports2.getFullscreenElement = getFullscreenElement;
exports2.getUnstableAudioFingerprint = getUnstableAudioFingerprint;
exports2.getUnstableCanvasFingerprint = getUnstableCanvasFingerprint;
exports2.getUnstableScreenFrame = getUnstableScreenFrame;
exports2.getUnstableScreenResolution = getUnstableScreenResolution;
exports2.getWebGLContext = getWebGLContext;
exports2.hashComponents = hashComponents;
exports2.isAndroid = isAndroid;
exports2.isChromium = isChromium;
exports2.isDesktopWebKit = isDesktopWebKit;
exports2.isEdgeHTML = isEdgeHTML;
exports2.isGecko = isGecko;
exports2.isSamsungInternet = isSamsungInternet;
exports2.isTrident = isTrident;
exports2.isWebKit = isWebKit;
exports2.load = load;
exports2.loadSources = loadSources;
exports2.murmurX64Hash128 = murmurX64Hash128;
exports2.prepareForSources = prepareForSources;
exports2.sources = sources;
exports2.transformSource = transformSource;
exports2.withIframe = withIframe;
}
});
// node_modules/@firebase/util/dist/postinstall.js
var require_postinstall = __commonJS({
"node_modules/@firebase/util/dist/postinstall.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
exports2.getDefaultsFromPostinstall = () => void 0;
}
});
// node_modules/@firebase/util/dist/index.node.cjs.js
var require_index_node_cjs = __commonJS({
"node_modules/@firebase/util/dist/index.node.cjs.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var postinstall = require_postinstall();
var CONSTANTS2 = {
/**
* @define {boolean} Whether this is the client Node.js SDK.
*/
NODE_CLIENT: false,
/**
* @define {boolean} Whether this is the Admin Node.js SDK.
*/
NODE_ADMIN: false,
/**
* Firebase SDK Version
*/
SDK_VERSION: "${JSCORE_VERSION}"
};
var assert = function(assertion, message) {
if (!assertion) {
throw assertionError(message);
}
};
var assertionError = function(message) {
return new Error("Firebase Database (" + CONSTANTS2.SDK_VERSION + ") INTERNAL ASSERT FAILED: " + message);
};
var stringToByteArray$12 = function(str) {
const out = [];
let p = 0;
for (let i = 0; i < str.length; i++) {
let c = str.charCodeAt(i);
if (c < 128) {
out[p++] = c;
} else if (c < 2048) {
out[p++] = c >> 6 | 192;
out[p++] = c & 63 | 128;
} else if ((c & 64512) === 55296 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) === 56320) {
c = 65536 + ((c & 1023) << 10) + (str.charCodeAt(++i) & 1023);
out[p++] = c >> 18 | 240;
out[p++] = c >> 12 & 63 | 128;
out[p++] = c >> 6 & 63 | 128;
out[p++] = c & 63 | 128;
} else {
out[p++] = c >> 12 | 224;
out[p++] = c >> 6 & 63 | 128;
out[p++] = c & 63 | 128;
}
}
return out;
};
var byteArrayToString2 = function(bytes) {
const out = [];
let pos = 0, c = 0;
while (pos < bytes.length) {
const c1 = bytes[pos++];
if (c1 < 128) {
out[c++] = String.fromCharCode(c1);
} else if (c1 > 191 && c1 < 224) {
const c2 = bytes[pos++];
out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
} else if (c1 > 239 && c1 < 365) {
const c2 = bytes[pos++];
const c3 = bytes[pos++];
const c4 = bytes[pos++];
const u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 65536;
out[c++] = String.fromCharCode(55296 + (u >> 10));
out[c++] = String.fromCharCode(56320 + (u & 1023));
} else {
const c2 = bytes[pos++];
const c3 = bytes[pos++];
out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
}
}
return out.join("");
};
var base642 = {
/**
* Maps bytes to characters.
*/
byteToCharMap_: null,
/**
* Maps characters to bytes.
*/
charToByteMap_: null,
/**
* Maps bytes to websafe characters.
* @private
*/
byteToCharMapWebSafe_: null,
/**
* Maps websafe characters to bytes.
* @private
*/
charToByteMapWebSafe_: null,
/**
* Our default alphabet, shared between
* ENCODED_VALS and ENCODED_VALS_WEBSAFE
*/
ENCODED_VALS_BASE: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
/**
* Our default alphabet. Value 64 (=) is special; it means "nothing."
*/
get ENCODED_VALS() {
return this.ENCODED_VALS_BASE + "+/=";
},
/**
* Our websafe alphabet.
*/
get ENCODED_VALS_WEBSAFE() {
return this.ENCODED_VALS_BASE + "-_.";
},
/**
* Whether this browser supports the atob and btoa functions. This extension
* started at Mozilla but is now implemented by many browsers. We use the
* ASSUME_* variables to avoid pulling in the full useragent detection library
* but still allowing the standard per-browser compilations.
*
*/
HAS_NATIVE_SUPPORT: typeof atob === "function",
/**
* Base64-encode an array of bytes.
*
* @param input An array of bytes (numbers with
* value in [0, 255]) to encode.
* @param webSafe Boolean indicating we should use the
* alternative alphabet.
* @return The base64 encoded string.
*/
encodeByteArray(input, webSafe) {
if (!Array.isArray(input)) {
throw Error("encodeByteArray takes an array as a parameter");
}
this.init_();
const byteToCharMap = webSafe ? this.byteToCharMapWebSafe_ : this.byteToCharMap_;
const output = [];
for (let i = 0; i < input.length; i += 3) {
const byte1 = input[i];
const haveByte2 = i + 1 < input.length;
const byte2 = haveByte2 ? input[i + 1] : 0;
const haveByte3 = i + 2 < input.length;
const byte3 = haveByte3 ? input[i + 2] : 0;
const outByte1 = byte1 >> 2;
const outByte2 = (byte1 & 3) << 4 | byte2 >> 4;
let outByte3 = (byte2 & 15) << 2 | byte3 >> 6;
let outByte4 = byte3 & 63;
if (!haveByte3) {
outByte4 = 64;
if (!haveByte2) {
outByte3 = 64;
}
}
output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
}
return output.join("");
},
/**
* Base64-encode a string.
*
* @param input A string to encode.
* @param webSafe If true, we should use the
* alternative alphabet.
* @return The base64 encoded string.
*/
encodeString(input, webSafe) {
if (this.HAS_NATIVE_SUPPORT && !webSafe) {
return btoa(input);
}
return this.encodeByteArray(stringToByteArray$12(input), webSafe);
},
/**
* Base64-decode a string.
*
* @param input to decode.
* @param webSafe True if we should use the
* alternative alphabet.
* @return string representing the decoded value.
*/
decodeString(input, webSafe) {
if (this.HAS_NATIVE_SUPPORT && !webSafe) {
return atob(input);
}
return byteArrayToString2(this.decodeStringToByteArray(input, webSafe));
},
/**
* Base64-decode a string.
*
* In base-64 decoding, groups of four characters are converted into three
* bytes. If the encoder did not apply padding, the input length may not
* be a multiple of 4.
*
* In this case, the last group will have fewer than 4 characters, and
* padding will be inferred. If the group has one or two characters, it decodes
* to one byte. If the group has three characters, it decodes to two bytes.
*
* @param input Input to decode.
* @param webSafe True if we should use the web-safe alphabet.
* @return bytes representing the decoded value.
*/
decodeStringToByteArray(input, webSafe) {
this.init_();
const charToByteMap = webSafe ? this.charToByteMapWebSafe_ : this.charToByteMap_;
const output = [];
for (let i = 0; i < input.length; ) {
const byte1 = charToByteMap[input.charAt(i++)];
const haveByte2 = i < input.length;
const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
++i;
const haveByte3 = i < input.length;
const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
++i;
const haveByte4 = i < input.length;
const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
++i;
if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
throw new DecodeBase64StringError2();
}
const outByte1 = byte1 << 2 | byte2 >> 4;
output.push(outByte1);
if (byte3 !== 64) {
const outByte2 = byte2 << 4 & 240 | byte3 >> 2;
output.push(outByte2);
if (byte4 !== 64) {
const outByte3 = byte3 << 6 & 192 | byte4;
output.push(outByte3);
}
}
}
return output;
},
/**
* Lazy static initialization function. Called before
* accessing any of the static map variables.
* @private
*/
init_() {
if (!this.byteToCharMap_) {
this.byteToCharMap_ = {};
this.charToByteMap_ = {};
this.byteToCharMapWebSafe_ = {};
this.charToByteMapWebSafe_ = {};
for (let i = 0; i < this.ENCODED_VALS.length; i++) {
this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
this.charToByteMap_[this.byteToCharMap_[i]] = i;
this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;
if (i >= this.ENCODED_VALS_BASE.length) {
this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
}
}
}
}
};
var DecodeBase64StringError2 = class extends Error {
constructor() {
super(...arguments);
this.name = "DecodeBase64StringError";
}
};
var base64Encode2 = function(str) {
const utf8Bytes = stringToByteArray$12(str);
return base642.encodeByteArray(utf8Bytes, true);
};
var base64urlEncodeWithoutPadding2 = function(str) {
return base64Encode2(str).replace(/\./g, "");
};
var base64Decode2 = function(str) {
try {
return base642.decodeString(str, true);
} catch (e) {
console.error("base64Decode failed: ", e);
}
return null;
};
function deepCopy(value) {
return deepExtend(void 0, value);
}
function deepExtend(target, source) {
if (!(source instanceof Object)) {
return source;
}
switch (source.constructor) {
case Date:
const dateValue = source;
return new Date(dateValue.getTime());
case Object:
if (target === void 0) {
target = {};
}
break;
case Array:
target = [];
break;
default:
return source;
}
for (const prop in source) {
if (!source.hasOwnProperty(prop) || !isValidKey(prop)) {
continue;
}
target[prop] = deepExtend(target[prop], source[prop]);
}
return target;
}
function isValidKey(key) {
return key !== "__proto__";
}
function getGlobal2() {
if (typeof self !== "undefined") {
return self;
}
if (typeof window !== "undefined") {
return window;
}
if (typeof global !== "undefined") {
return global;
}
throw new Error("Unable to locate global object.");
}
var getDefaultsFromGlobal2 = () => getGlobal2().__FIREBASE_DEFAULTS__;
var getDefaultsFromEnvVariable2 = () => {
if (typeof process === "undefined" || typeof process.env === "undefined") {
return;
}
const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;
if (defaultsJsonString) {
return JSON.parse(defaultsJsonString);
}
};
var getDefaultsFromCookie2 = () => {
if (typeof document === "undefined") {
return;
}
let match;
try {
match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
} catch (e) {
return;
}
const decoded = match && base64Decode2(match[1]);
return decoded && JSON.parse(decoded);
};
var getDefaults2 = () => {
try {
return postinstall.getDefaultsFromPostinstall() || getDefaultsFromGlobal2() || getDefaultsFromEnvVariable2() || getDefaultsFromCookie2();
} catch (e) {
console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
return;
}
};
var getDefaultEmulatorHost2 = (productName) => getDefaults2()?.emulatorHosts?.[productName];
var getDefaultEmulatorHostnameAndPort2 = (productName) => {
const host = getDefaultEmulatorHost2(productName);
if (!host) {
return void 0;
}
const separatorIndex = host.lastIndexOf(":");
if (separatorIndex <= 0 || separatorIndex + 1 === host.length) {
throw new Error(`Invalid host ${host} with no separate hostname and port!`);
}
const port = parseInt(host.substring(separatorIndex + 1), 10);
if (host[0] === "[") {
return [host.substring(1, separatorIndex - 1), port];
} else {
return [host.substring(0, separatorIndex), port];
}
};
var getDefaultAppConfig2 = () => getDefaults2()?.config;
var getExperimentalSetting = (name6) => getDefaults2()?.[`_${name6}`];
var Deferred2 = class {
constructor() {
this.reject = () => {
};
this.resolve = () => {
};
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
/**
* Our API internals are not promisified and cannot because our callback APIs have subtle expectations around
* invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
* and returns a node-style callback which will resolve or reject the Deferred's promise.
*/
wrapCallback(callback) {
return (error, value) => {
if (error) {
this.reject(error);
} else {
this.resolve(value);
}
if (typeof callback === "function") {
this.promise.catch(() => {
});
if (callback.length === 1) {
callback(error);
} else {
callback(error, value);
}
}
};
}
};
function isCloudWorkstation2(url) {
try {
const host = url.startsWith("http://") || url.startsWith("https://") ? new URL(url).hostname : url;
return host.endsWith(".cloudworkstations.dev");
} catch {
return false;
}
}
async function pingServer2(endpoint) {
const result = await fetch(endpoint, {
credentials: "include"
});
return result.ok;
}
function createMockUserToken2(token, projectId) {
if (token.uid) {
throw new Error('The "uid" field is no longer supported by mockUserToken. Please use "sub" instead for Firebase Auth User ID.');
}
const header = {
alg: "none",
type: "JWT"
};
const project = projectId || "demo-project";
const iat = token.iat || 0;
const sub = token.sub || token.user_id;
if (!sub) {
throw new Error("mockUserToken must contain 'sub' or 'user_id' field!");
}
const payload = {
// Set all required fields to decent defaults
iss: `https://securetoken.google.com/${project}`,
aud: project,
iat,
exp: iat + 3600,
auth_time: iat,
sub,
user_id: sub,
firebase: {
sign_in_provider: "custom",
identities: {}
},
// Override with user options
...token
};
const signature = "";
return [
base64urlEncodeWithoutPadding2(JSON.stringify(header)),
base64urlEncodeWithoutPadding2(JSON.stringify(payload)),
signature
].join(".");
}
var emulatorStatus2 = {};
function getEmulatorSummary2() {
const summary = {
prod: [],
emulator: []
};
for (const key of Object.keys(emulatorStatus2)) {
if (emulatorStatus2[key]) {
summary.emulator.push(key);
} else {
summary.prod.push(key);
}
}
return summary;
}
function getOrCreateEl2(id) {
let parentDiv = document.getElementById(id);
let created = false;
if (!parentDiv) {
parentDiv = document.createElement("div");
parentDiv.setAttribute("id", id);
created = true;
}
return { created, element: parentDiv };
}
var previouslyDismissed2 = false;
function updateEmulatorBanner2(name6, isRunningEmulator) {
if (typeof window === "undefined" || typeof document === "undefined" || !isCloudWorkstation2(window.location.host) || emulatorStatus2[name6] === isRunningEmulator || emulatorStatus2[name6] || // If already set to use emulator, can't go back to prod.
previouslyDismissed2) {
return;
}
emulatorStatus2[name6] = isRunningEmulator;
function prefixedId(id) {
return `__firebase__banner__${id}`;
}
const bannerId = "__firebase__banner";
const summary = getEmulatorSummary2();
const showError = summary.prod.length > 0;
function tearDown() {
const element = document.getElementById(bannerId);
if (element) {
element.remove();
}
}
function setupBannerStyles(bannerEl) {
bannerEl.style.display = "flex";
bannerEl.style.background = "#7faaf0";
bannerEl.style.position = "fixed";
bannerEl.style.bottom = "5px";
bannerEl.style.left = "5px";
bannerEl.style.padding = ".5em";
bannerEl.style.borderRadius = "5px";
bannerEl.style.alignItems = "center";
}
function setupIconStyles(prependIcon, iconId) {
prependIcon.setAttribute("width", "24");
prependIcon.setAttribute("id", iconId);
prependIcon.setAttribute("height", "24");
prependIcon.setAttribute("viewBox", "0 0 24 24");
prependIcon.setAttribute("fill", "none");
prependIcon.style.marginLeft = "-6px";
}
function setupCloseBtn() {
const closeBtn = document.createElement("span");
closeBtn.style.cursor = "pointer";
closeBtn.style.marginLeft = "16px";
closeBtn.style.fontSize = "24px";
closeBtn.innerHTML = " &times;";
closeBtn.onclick = () => {
previouslyDismissed2 = true;
tearDown();
};
return closeBtn;
}
function setupLinkStyles(learnMoreLink, learnMoreId) {
learnMoreLink.setAttribute("id", learnMoreId);
learnMoreLink.innerText = "Learn more";
learnMoreLink.href = "https://firebase.google.com/docs/studio/preview-apps#preview-backend";
learnMoreLink.setAttribute("target", "__blank");
learnMoreLink.style.paddingLeft = "5px";
learnMoreLink.style.textDecoration = "underline";
}
function setupDom() {
const banner = getOrCreateEl2(bannerId);
const firebaseTextId = prefixedId("text");
const firebaseText = document.getElementById(firebaseTextId) || document.createElement("span");
const learnMoreId = prefixedId("learnmore");
const learnMoreLink = document.getElementById(learnMoreId) || document.createElement("a");
const prependIconId = prefixedId("preprendIcon");
const prependIcon = document.getElementById(prependIconId) || document.createElementNS("http://www.w3.org/2000/svg", "svg");
if (banner.created) {
const bannerEl = banner.element;
setupBannerStyles(bannerEl);
setupLinkStyles(learnMoreLink, learnMoreId);
const closeBtn = setupCloseBtn();
setupIconStyles(prependIcon, prependIconId);
bannerEl.append(prependIcon, firebaseText, learnMoreLink, closeBtn);
document.body.appendChild(bannerEl);
}
if (showError) {
firebaseText.innerText = `Preview backend disconnected.`;
prependIcon.innerHTML = `<g clip-path="url(#clip0_6013_33858)">
<path d="M4.8 17.6L12 5.6L19.2 17.6H4.8ZM6.91667 16.4H17.0833L12 7.93333L6.91667 16.4ZM12 15.6C12.1667 15.6 12.3056 15.5444 12.4167 15.4333C12.5389 15.3111 12.6 15.1667 12.6 15C12.6 14.8333 12.5389 14.6944 12.4167 14.5833C12.3056 14.4611 12.1667 14.4 12 14.4C11.8333 14.4 11.6889 14.4611 11.5667 14.5833C11.4556 14.6944 11.4 14.8333 11.4 15C11.4 15.1667 11.4556 15.3111 11.5667 15.4333C11.6889 15.5444 11.8333 15.6 12 15.6ZM11.4 13.6H12.6V10.4H11.4V13.6Z" fill="#212121"/>
</g>
<defs>
<clipPath id="clip0_6013_33858">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>`;
} else {
prependIcon.innerHTML = `<g clip-path="url(#clip0_6083_34804)">
<path d="M11.4 15.2H12.6V11.2H11.4V15.2ZM12 10C12.1667 10 12.3056 9.94444 12.4167 9.83333C12.5389 9.71111 12.6 9.56667 12.6 9.4C12.6 9.23333 12.5389 9.09444 12.4167 8.98333C12.3056 8.86111 12.1667 8.8 12 8.8C11.8333 8.8 11.6889 8.86111 11.5667 8.98333C11.4556 9.09444 11.4 9.23333 11.4 9.4C11.4 9.56667 11.4556 9.71111 11.5667 9.83333C11.6889 9.94444 11.8333 10 12 10ZM12 18.4C11.1222 18.4 10.2944 18.2333 9.51667 17.9C8.73889 17.5667 8.05556 17.1111 7.46667 16.5333C6.88889 15.9444 6.43333 15.2611 6.1 14.4833C5.76667 13.7056 5.6 12.8778 5.6 12C5.6 11.1111 5.76667 10.2833 6.1 9.51667C6.43333 8.73889 6.88889 8.06111 7.46667 7.48333C8.05556 6.89444 8.73889 6.43333 9.51667 6.1C10.2944 5.76667 11.1222 5.6 12 5.6C12.8889 5.6 13.7167 5.76667 14.4833 6.1C15.2611 6.43333 15.9389 6.89444 16.5167 7.48333C17.1056 8.06111 17.5667 8.73889 17.9 9.51667C18.2333 10.2833 18.4 11.1111 18.4 12C18.4 12.8778 18.2333 13.7056 17.9 14.4833C17.5667 15.2611 17.1056 15.9444 16.5167 16.5333C15.9389 17.1111 15.2611 17.5667 14.4833 17.9C13.7167 18.2333 12.8889 18.4 12 18.4ZM12 17.2C13.4444 17.2 14.6722 16.6944 15.6833 15.6833C16.6944 14.6722 17.2 13.4444 17.2 12C17.2 10.5556 16.6944 9.32778 15.6833 8.31667C14.6722 7.30555 13.4444 6.8 12 6.8C10.5556 6.8 9.32778 7.30555 8.31667 8.31667C7.30556 9.32778 6.8 10.5556 6.8 12C6.8 13.4444 7.30556 14.6722 8.31667 15.6833C9.32778 16.6944 10.5556 17.2 12 17.2Z" fill="#212121"/>
</g>
<defs>
<clipPath id="clip0_6083_34804">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>`;
firebaseText.innerText = "Preview backend running in this workspace.";
}
firebaseText.setAttribute("id", firebaseTextId);
}
if (document.readyState === "loading") {
window.addEventListener("DOMContentLoaded", setupDom);
} else {
setupDom();
}
}
function getUA2() {
if (typeof navigator !== "undefined" && typeof navigator["userAgent"] === "string") {
return navigator["userAgent"];
} else {
return "";
}
}
function isMobileCordova2() {
return typeof window !== "undefined" && // @ts-ignore Setting up an broadly applicable index signature for Window
// just to deal with this case would probably be a bad idea.
!!(window["cordova"] || window["phonegap"] || window["PhoneGap"]) && /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA2());
}
function isNode() {
const forceEnvironment = getDefaults2()?.forceEnvironment;
if (forceEnvironment === "node") {
return true;
} else if (forceEnvironment === "browser") {
return false;
}
try {
return Object.prototype.toString.call(global.process) === "[object process]";
} catch (e) {
return false;
}
}
function isBrowser2() {
return typeof window !== "undefined" || isWebWorker2();
}
function isWebWorker2() {
return typeof WorkerGlobalScope !== "undefined" && typeof self !== "undefined" && self instanceof WorkerGlobalScope;
}
function isCloudflareWorker2() {
return typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers";
}
function isBrowserExtension2() {
const runtime = typeof chrome === "object" ? chrome.runtime : typeof browser === "object" ? browser.runtime : void 0;
return typeof runtime === "object" && runtime.id !== void 0;
}
function isReactNative2() {
return typeof navigator === "object" && navigator["product"] === "ReactNative";
}
function isElectron() {
return getUA2().indexOf("Electron/") >= 0;
}
function isIE2() {
const ua = getUA2();
return ua.indexOf("MSIE ") >= 0 || ua.indexOf("Trident/") >= 0;
}
function isUWP() {
return getUA2().indexOf("MSAppHost/") >= 0;
}
function isNodeSdk() {
return CONSTANTS2.NODE_CLIENT === true || CONSTANTS2.NODE_ADMIN === true;
}
function isSafari() {
return !isNode() && !!navigator.userAgent && navigator.userAgent.includes("Safari") && !navigator.userAgent.includes("Chrome");
}
function isSafariOrWebkit() {
return !isNode() && !!navigator.userAgent && (navigator.userAgent.includes("Safari") || navigator.userAgent.includes("WebKit")) && !navigator.userAgent.includes("Chrome");
}
function isIndexedDBAvailable2() {
try {
return typeof indexedDB === "object";
} catch (e) {
return false;
}
}
function validateIndexedDBOpenable2() {
return new Promise((resolve, reject) => {
try {
let preExist = true;
const DB_CHECK_NAME = "validate-browser-context-for-indexeddb-analytics-module";
const request = self.indexedDB.open(DB_CHECK_NAME);
request.onsuccess = () => {
request.result.close();
if (!preExist) {
self.indexedDB.deleteDatabase(DB_CHECK_NAME);
}
resolve(true);
};
request.onupgradeneeded = () => {
preExist = false;
};
request.onerror = () => {
reject(request.error?.message || "");
};
} catch (error) {
reject(error);
}
});
}
function areCookiesEnabled() {
if (typeof navigator === "undefined" || !navigator.cookieEnabled) {
return false;
}
return true;
}
var ERROR_NAME2 = "FirebaseError";
var FirebaseError2 = class _FirebaseError extends Error {
constructor(code, message, customData) {
super(message);
this.code = code;
this.customData = customData;
this.name = ERROR_NAME2;
Object.setPrototypeOf(this, _FirebaseError.prototype);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ErrorFactory2.prototype.create);
}
}
};
var ErrorFactory2 = class {
constructor(service, serviceName, errors) {
this.service = service;
this.serviceName = serviceName;
this.errors = errors;
}
create(code, ...data) {
const customData = data[0] || {};
const fullCode = `${this.service}/${code}`;
const template = this.errors[code];
const message = template ? replaceTemplate2(template, customData) : "Error";
const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
const error = new FirebaseError2(fullCode, fullMessage, customData);
return error;
}
};
function replaceTemplate2(template, data) {
return template.replace(PATTERN2, (_, key) => {
const value = data[key];
return value != null ? String(value) : `<${key}?>`;
});
}
var PATTERN2 = /\{\$([^}]+)}/g;
function jsonEval(str) {
return JSON.parse(str);
}
function stringify(data) {
return JSON.stringify(data);
}
var decode2 = function(token) {
let header = {}, claims = {}, data = {}, signature = "";
try {
const parts = token.split(".");
header = jsonEval(base64Decode2(parts[0]) || "");
claims = jsonEval(base64Decode2(parts[1]) || "");
signature = parts[2];
data = claims["d"] || {};
delete claims["d"];
} catch (e) {
}
return {
header,
claims,
data,
signature
};
};
var isValidTimestamp = function(token) {
const claims = decode2(token).claims;
const now = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
let validSince = 0, validUntil = 0;
if (typeof claims === "object") {
if (claims.hasOwnProperty("nbf")) {
validSince = claims["nbf"];
} else if (claims.hasOwnProperty("iat")) {
validSince = claims["iat"];
}
if (claims.hasOwnProperty("exp")) {
validUntil = claims["exp"];
} else {
validUntil = validSince + 86400;
}
}
return !!now && !!validSince && !!validUntil && now >= validSince && now <= validUntil;
};
var issuedAtTime = function(token) {
const claims = decode2(token).claims;
if (typeof claims === "object" && claims.hasOwnProperty("iat")) {
return claims["iat"];
}
return null;
};
var isValidFormat = function(token) {
const decoded = decode2(token), claims = decoded.claims;
return !!claims && typeof claims === "object" && claims.hasOwnProperty("iat");
};
var isAdmin = function(token) {
const claims = decode2(token).claims;
return typeof claims === "object" && claims["admin"] === true;
};
function contains(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
}
function safeGet(obj, key) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return obj[key];
} else {
return void 0;
}
}
function isEmpty(obj) {
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
function map(obj, fn, contextObj) {
const res = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
res[key] = fn.call(contextObj, obj[key], key, obj);
}
}
return res;
}
function deepEqual2(a, b) {
if (a === b) {
return true;
}
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
for (const k of aKeys) {
if (!bKeys.includes(k)) {
return false;
}
const aProp = a[k];
const bProp = b[k];
if (isObject2(aProp) && isObject2(bProp)) {
if (!deepEqual2(aProp, bProp)) {
return false;
}
} else if (aProp !== bProp) {
return false;
}
}
for (const k of bKeys) {
if (!aKeys.includes(k)) {
return false;
}
}
return true;
}
function isObject2(thing) {
return thing !== null && typeof thing === "object";
}
function promiseWithTimeout(promise, timeInMS = 2e3) {
const deferredPromise = new Deferred2();
setTimeout(() => deferredPromise.reject("timeout!"), timeInMS);
promise.then(deferredPromise.resolve, deferredPromise.reject);
return deferredPromise.promise;
}
function querystring2(querystringParams) {
const params = [];
for (const [key, value] of Object.entries(querystringParams)) {
if (Array.isArray(value)) {
value.forEach((arrayVal) => {
params.push(encodeURIComponent(key) + "=" + encodeURIComponent(arrayVal));
});
} else {
params.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
}
return params.length ? "&" + params.join("&") : "";
}
function querystringDecode2(querystring3) {
const obj = {};
const tokens = querystring3.replace(/^\?/, "").split("&");
tokens.forEach((token) => {
if (token) {
const [key, value] = token.split("=");
obj[decodeURIComponent(key)] = decodeURIComponent(value);
}
});
return obj;
}
function extractQuerystring2(url) {
const queryStart = url.indexOf("?");
if (!queryStart) {
return "";
}
const fragmentStart = url.indexOf("#", queryStart);
return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : void 0);
}
var Sha1 = class {
constructor() {
this.chain_ = [];
this.buf_ = [];
this.W_ = [];
this.pad_ = [];
this.inbuf_ = 0;
this.total_ = 0;
this.blockSize = 512 / 8;
this.pad_[0] = 128;
for (let i = 1; i < this.blockSize; ++i) {
this.pad_[i] = 0;
}
this.reset();
}
reset() {
this.chain_[0] = 1732584193;
this.chain_[1] = 4023233417;
this.chain_[2] = 2562383102;
this.chain_[3] = 271733878;
this.chain_[4] = 3285377520;
this.inbuf_ = 0;
this.total_ = 0;
}
/**
* Internal compress helper function.
* @param buf Block to compress.
* @param offset Offset of the block in the buffer.
* @private
*/
compress_(buf, offset) {
if (!offset) {
offset = 0;
}
const W = this.W_;
if (typeof buf === "string") {
for (let i = 0; i < 16; i++) {
W[i] = buf.charCodeAt(offset) << 24 | buf.charCodeAt(offset + 1) << 16 | buf.charCodeAt(offset + 2) << 8 | buf.charCodeAt(offset + 3);
offset += 4;
}
} else {
for (let i = 0; i < 16; i++) {
W[i] = buf[offset] << 24 | buf[offset + 1] << 16 | buf[offset + 2] << 8 | buf[offset + 3];
offset += 4;
}
}
for (let i = 16; i < 80; i++) {
const t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = (t << 1 | t >>> 31) & 4294967295;
}
let a = this.chain_[0];
let b = this.chain_[1];
let c = this.chain_[2];
let d = this.chain_[3];
let e = this.chain_[4];
let f, k;
for (let i = 0; i < 80; i++) {
if (i < 40) {
if (i < 20) {
f = d ^ b & (c ^ d);
k = 1518500249;
} else {
f = b ^ c ^ d;
k = 1859775393;
}
} else {
if (i < 60) {
f = b & c | d & (b | c);
k = 2400959708;
} else {
f = b ^ c ^ d;
k = 3395469782;
}
}
const t = (a << 5 | a >>> 27) + f + e + k + W[i] & 4294967295;
e = d;
d = c;
c = (b << 30 | b >>> 2) & 4294967295;
b = a;
a = t;
}
this.chain_[0] = this.chain_[0] + a & 4294967295;
this.chain_[1] = this.chain_[1] + b & 4294967295;
this.chain_[2] = this.chain_[2] + c & 4294967295;
this.chain_[3] = this.chain_[3] + d & 4294967295;
this.chain_[4] = this.chain_[4] + e & 4294967295;
}
update(bytes, length) {
if (bytes == null) {
return;
}
if (length === void 0) {
length = bytes.length;
}
const lengthMinusBlock = length - this.blockSize;
let n = 0;
const buf = this.buf_;
let inbuf = this.inbuf_;
while (n < length) {
if (inbuf === 0) {
while (n <= lengthMinusBlock) {
this.compress_(bytes, n);
n += this.blockSize;
}
}
if (typeof bytes === "string") {
while (n < length) {
buf[inbuf] = bytes.charCodeAt(n);
++inbuf;
++n;
if (inbuf === this.blockSize) {
this.compress_(buf);
inbuf = 0;
break;
}
}
} else {
while (n < length) {
buf[inbuf] = bytes[n];
++inbuf;
++n;
if (inbuf === this.blockSize) {
this.compress_(buf);
inbuf = 0;
break;
}
}
}
}
this.inbuf_ = inbuf;
this.total_ += length;
}
/** @override */
digest() {
const digest = [];
let totalBits = this.total_ * 8;
if (this.inbuf_ < 56) {
this.update(this.pad_, 56 - this.inbuf_);
} else {
this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));
}
for (let i = this.blockSize - 1; i >= 56; i--) {
this.buf_[i] = totalBits & 255;
totalBits /= 256;
}
this.compress_(this.buf_);
let n = 0;
for (let i = 0; i < 5; i++) {
for (let j = 24; j >= 0; j -= 8) {
digest[n] = this.chain_[i] >> j & 255;
++n;
}
}
return digest;
}
};
function createSubscribe2(executor, onNoObservers) {
const proxy = new ObserverProxy2(executor, onNoObservers);
return proxy.subscribe.bind(proxy);
}
var ObserverProxy2 = class {
/**
* @param executor Function which can make calls to a single Observer
* as a proxy.
* @param onNoObservers Callback when count of Observers goes to zero.
*/
constructor(executor, onNoObservers) {
this.observers = [];
this.unsubscribes = [];
this.observerCount = 0;
this.task = Promise.resolve();
this.finalized = false;
this.onNoObservers = onNoObservers;
this.task.then(() => {
executor(this);
}).catch((e) => {
this.error(e);
});
}
next(value) {
this.forEachObserver((observer) => {
observer.next(value);
});
}
error(error) {
this.forEachObserver((observer) => {
observer.error(error);
});
this.close(error);
}
complete() {
this.forEachObserver((observer) => {
observer.complete();
});
this.close();
}
/**
* Subscribe function that can be used to add an Observer to the fan-out list.
*
* - We require that no event is sent to a subscriber synchronously to their
* call to subscribe().
*/
subscribe(nextOrObserver, error, complete) {
let observer;
if (nextOrObserver === void 0 && error === void 0 && complete === void 0) {
throw new Error("Missing Observer.");
}
if (implementsAnyMethods2(nextOrObserver, [
"next",
"error",
"complete"
])) {
observer = nextOrObserver;
} else {
observer = {
next: nextOrObserver,
error,
complete
};
}
if (observer.next === void 0) {
observer.next = noop2;
}
if (observer.error === void 0) {
observer.error = noop2;
}
if (observer.complete === void 0) {
observer.complete = noop2;
}
const unsub = this.unsubscribeOne.bind(this, this.observers.length);
if (this.finalized) {
this.task.then(() => {
try {
if (this.finalError) {
observer.error(this.finalError);
} else {
observer.complete();
}
} catch (e) {
}
return;
});
}
this.observers.push(observer);
return unsub;
}
// Unsubscribe is synchronous - we guarantee that no events are sent to
// any unsubscribed Observer.
unsubscribeOne(i) {
if (this.observers === void 0 || this.observers[i] === void 0) {
return;
}
delete this.observers[i];
this.observerCount -= 1;
if (this.observerCount === 0 && this.onNoObservers !== void 0) {
this.onNoObservers(this);
}
}
forEachObserver(fn) {
if (this.finalized) {
return;
}
for (let i = 0; i < this.observers.length; i++) {
this.sendOne(i, fn);
}
}
// Call the Observer via one of it's callback function. We are careful to
// confirm that the observe has not been unsubscribed since this asynchronous
// function had been queued.
sendOne(i, fn) {
this.task.then(() => {
if (this.observers !== void 0 && this.observers[i] !== void 0) {
try {
fn(this.observers[i]);
} catch (e) {
if (typeof console !== "undefined" && console.error) {
console.error(e);
}
}
}
});
}
close(err) {
if (this.finalized) {
return;
}
this.finalized = true;
if (err !== void 0) {
this.finalError = err;
}
this.task.then(() => {
this.observers = void 0;
this.onNoObservers = void 0;
});
}
};
function async(fn, onError) {
return (...args) => {
Promise.resolve(true).then(() => {
fn(...args);
}).catch((error) => {
if (onError) {
onError(error);
}
});
};
}
function implementsAnyMethods2(obj, methods) {
if (typeof obj !== "object" || obj === null) {
return false;
}
for (const method of methods) {
if (method in obj && typeof obj[method] === "function") {
return true;
}
}
return false;
}
function noop2() {
}
var validateArgCount = function(fnName, minCount, maxCount, argCount) {
let argError;
if (argCount < minCount) {
argError = "at least " + minCount;
} else if (argCount > maxCount) {
argError = maxCount === 0 ? "none" : "no more than " + maxCount;
}
if (argError) {
const error = fnName + " failed: Was called with " + argCount + (argCount === 1 ? " argument." : " arguments.") + " Expects " + argError + ".";
throw new Error(error);
}
};
function errorPrefix(fnName, argName) {
return `${fnName} failed: ${argName} argument `;
}
function validateNamespace(fnName, namespace, optional) {
if (optional && !namespace) {
return;
}
if (typeof namespace !== "string") {
throw new Error(errorPrefix(fnName, "namespace") + "must be a valid firebase namespace.");
}
}
function validateCallback(fnName, argumentName, callback, optional) {
if (optional && !callback) {
return;
}
if (typeof callback !== "function") {
throw new Error(errorPrefix(fnName, argumentName) + "must be a valid function.");
}
}
function validateContextObject(fnName, argumentName, context, optional) {
if (optional && !context) {
return;
}
if (typeof context !== "object" || context === null) {
throw new Error(errorPrefix(fnName, argumentName) + "must be a valid context object.");
}
}
var stringToByteArray = function(str) {
const out = [];
let p = 0;
for (let i = 0; i < str.length; i++) {
let c = str.charCodeAt(i);
if (c >= 55296 && c <= 56319) {
const high = c - 55296;
i++;
assert(i < str.length, "Surrogate pair missing trail surrogate.");
const low = str.charCodeAt(i) - 56320;
c = 65536 + (high << 10) + low;
}
if (c < 128) {
out[p++] = c;
} else if (c < 2048) {
out[p++] = c >> 6 | 192;
out[p++] = c & 63 | 128;
} else if (c < 65536) {
out[p++] = c >> 12 | 224;
out[p++] = c >> 6 & 63 | 128;
out[p++] = c & 63 | 128;
} else {
out[p++] = c >> 18 | 240;
out[p++] = c >> 12 & 63 | 128;
out[p++] = c >> 6 & 63 | 128;
out[p++] = c & 63 | 128;
}
}
return out;
};
var stringLength = function(str) {
let p = 0;
for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
if (c < 128) {
p++;
} else if (c < 2048) {
p += 2;
} else if (c >= 55296 && c <= 56319) {
p += 4;
i++;
} else {
p += 3;
}
}
return p;
};
var DEFAULT_INTERVAL_MILLIS = 1e3;
var DEFAULT_BACKOFF_FACTOR = 2;
var MAX_VALUE_MILLIS2 = 4 * 60 * 60 * 1e3;
var RANDOM_FACTOR = 0.5;
function calculateBackoffMillis(backoffCount, intervalMillis = DEFAULT_INTERVAL_MILLIS, backoffFactor = DEFAULT_BACKOFF_FACTOR) {
const currBaseValue = intervalMillis * Math.pow(backoffFactor, backoffCount);
const randomWait = Math.round(
// A fraction of the backoff value to add/subtract.
// Deviation: changes multiplication order to improve readability.
RANDOM_FACTOR * currBaseValue * // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines
// if we add or subtract.
(Math.random() - 0.5) * 2
);
return Math.min(MAX_VALUE_MILLIS2, currBaseValue + randomWait);
}
function ordinal(i) {
if (!Number.isFinite(i)) {
return `${i}`;
}
return i + indicator(i);
}
function indicator(i) {
i = Math.abs(i);
const cent = i % 100;
if (cent >= 10 && cent <= 20) {
return "th";
}
const dec = i % 10;
if (dec === 1) {
return "st";
}
if (dec === 2) {
return "nd";
}
if (dec === 3) {
return "rd";
}
return "th";
}
function getModularInstance2(service) {
if (service && service._delegate) {
return service._delegate;
} else {
return service;
}
}
CONSTANTS2.NODE_CLIENT = true;
exports2.CONSTANTS = CONSTANTS2;
exports2.DecodeBase64StringError = DecodeBase64StringError2;
exports2.Deferred = Deferred2;
exports2.ErrorFactory = ErrorFactory2;
exports2.FirebaseError = FirebaseError2;
exports2.MAX_VALUE_MILLIS = MAX_VALUE_MILLIS2;
exports2.RANDOM_FACTOR = RANDOM_FACTOR;
exports2.Sha1 = Sha1;
exports2.areCookiesEnabled = areCookiesEnabled;
exports2.assert = assert;
exports2.assertionError = assertionError;
exports2.async = async;
exports2.base64 = base642;
exports2.base64Decode = base64Decode2;
exports2.base64Encode = base64Encode2;
exports2.base64urlEncodeWithoutPadding = base64urlEncodeWithoutPadding2;
exports2.calculateBackoffMillis = calculateBackoffMillis;
exports2.contains = contains;
exports2.createMockUserToken = createMockUserToken2;
exports2.createSubscribe = createSubscribe2;
exports2.decode = decode2;
exports2.deepCopy = deepCopy;
exports2.deepEqual = deepEqual2;
exports2.deepExtend = deepExtend;
exports2.errorPrefix = errorPrefix;
exports2.extractQuerystring = extractQuerystring2;
exports2.getDefaultAppConfig = getDefaultAppConfig2;
exports2.getDefaultEmulatorHost = getDefaultEmulatorHost2;
exports2.getDefaultEmulatorHostnameAndPort = getDefaultEmulatorHostnameAndPort2;
exports2.getDefaults = getDefaults2;
exports2.getExperimentalSetting = getExperimentalSetting;
exports2.getGlobal = getGlobal2;
exports2.getModularInstance = getModularInstance2;
exports2.getUA = getUA2;
exports2.isAdmin = isAdmin;
exports2.isBrowser = isBrowser2;
exports2.isBrowserExtension = isBrowserExtension2;
exports2.isCloudWorkstation = isCloudWorkstation2;
exports2.isCloudflareWorker = isCloudflareWorker2;
exports2.isElectron = isElectron;
exports2.isEmpty = isEmpty;
exports2.isIE = isIE2;
exports2.isIndexedDBAvailable = isIndexedDBAvailable2;
exports2.isMobileCordova = isMobileCordova2;
exports2.isNode = isNode;
exports2.isNodeSdk = isNodeSdk;
exports2.isReactNative = isReactNative2;
exports2.isSafari = isSafari;
exports2.isSafariOrWebkit = isSafariOrWebkit;
exports2.isUWP = isUWP;
exports2.isValidFormat = isValidFormat;
exports2.isValidTimestamp = isValidTimestamp;
exports2.isWebWorker = isWebWorker2;
exports2.issuedAtTime = issuedAtTime;
exports2.jsonEval = jsonEval;
exports2.map = map;
exports2.ordinal = ordinal;
exports2.pingServer = pingServer2;
exports2.promiseWithTimeout = promiseWithTimeout;
exports2.querystring = querystring2;
exports2.querystringDecode = querystringDecode2;
exports2.safeGet = safeGet;
exports2.stringLength = stringLength;
exports2.stringToByteArray = stringToByteArray;
exports2.stringify = stringify;
exports2.updateEmulatorBanner = updateEmulatorBanner2;
exports2.validateArgCount = validateArgCount;
exports2.validateCallback = validateCallback;
exports2.validateContextObject = validateContextObject;
exports2.validateIndexedDBOpenable = validateIndexedDBOpenable2;
exports2.validateNamespace = validateNamespace;
}
});
// node_modules/@firebase/component/dist/index.cjs.js
var require_index_cjs = __commonJS({
"node_modules/@firebase/component/dist/index.cjs.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var util = require_index_node_cjs();
var Component2 = class {
/**
*
* @param name The public service name, e.g. app, auth, firestore, database
* @param instanceFactory Service factory responsible for creating the public interface
* @param type whether the service provided by the component is public or private
*/
constructor(name6, instanceFactory, type) {
this.name = name6;
this.instanceFactory = instanceFactory;
this.type = type;
this.multipleInstances = false;
this.serviceProps = {};
this.instantiationMode = "LAZY";
this.onInstanceCreated = null;
}
setInstantiationMode(mode) {
this.instantiationMode = mode;
return this;
}
setMultipleInstances(multipleInstances) {
this.multipleInstances = multipleInstances;
return this;
}
setServiceProps(props) {
this.serviceProps = props;
return this;
}
setInstanceCreatedCallback(callback) {
this.onInstanceCreated = callback;
return this;
}
};
var DEFAULT_ENTRY_NAME3 = "[DEFAULT]";
var Provider2 = class {
constructor(name6, container) {
this.name = name6;
this.container = container;
this.component = null;
this.instances = /* @__PURE__ */ new Map();
this.instancesDeferred = /* @__PURE__ */ new Map();
this.instancesOptions = /* @__PURE__ */ new Map();
this.onInitCallbacks = /* @__PURE__ */ new Map();
}
/**
* @param identifier A provider can provide multiple instances of a service
* if this.component.multipleInstances is true.
*/
get(identifier) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
if (!this.instancesDeferred.has(normalizedIdentifier)) {
const deferred = new util.Deferred();
this.instancesDeferred.set(normalizedIdentifier, deferred);
if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) {
try {
const instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
if (instance) {
deferred.resolve(instance);
}
} catch (e) {
}
}
}
return this.instancesDeferred.get(normalizedIdentifier).promise;
}
getImmediate(options) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(options?.identifier);
const optional = options?.optional ?? false;
if (this.isInitialized(normalizedIdentifier) || this.shouldAutoInitialize()) {
try {
return this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
} catch (e) {
if (optional) {
return null;
} else {
throw e;
}
}
} else {
if (optional) {
return null;
} else {
throw Error(`Service ${this.name} is not available`);
}
}
}
getComponent() {
return this.component;
}
setComponent(component) {
if (component.name !== this.name) {
throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
}
if (this.component) {
throw Error(`Component for ${this.name} has already been provided`);
}
this.component = component;
if (!this.shouldAutoInitialize()) {
return;
}
if (isComponentEager2(component)) {
try {
this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME3 });
} catch (e) {
}
}
for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
try {
const instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier
});
instanceDeferred.resolve(instance);
} catch (e) {
}
}
}
clearInstance(identifier = DEFAULT_ENTRY_NAME3) {
this.instancesDeferred.delete(identifier);
this.instancesOptions.delete(identifier);
this.instances.delete(identifier);
}
// app.delete() will call this method on every provider to delete the services
// TODO: should we mark the provider as deleted?
async delete() {
const services = Array.from(this.instances.values());
await Promise.all([
...services.filter((service) => "INTERNAL" in service).map((service) => service.INTERNAL.delete()),
...services.filter((service) => "_delete" in service).map((service) => service._delete())
]);
}
isComponentSet() {
return this.component != null;
}
isInitialized(identifier = DEFAULT_ENTRY_NAME3) {
return this.instances.has(identifier);
}
getOptions(identifier = DEFAULT_ENTRY_NAME3) {
return this.instancesOptions.get(identifier) || {};
}
initialize(opts = {}) {
const { options = {} } = opts;
const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
if (this.isInitialized(normalizedIdentifier)) {
throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
}
if (!this.isComponentSet()) {
throw Error(`Component ${this.name} has not been registered yet`);
}
const instance = this.getOrInitializeService({
instanceIdentifier: normalizedIdentifier,
options
});
for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
if (normalizedIdentifier === normalizedDeferredIdentifier) {
instanceDeferred.resolve(instance);
}
}
return instance;
}
/**
*
* @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().
* The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
*
* @param identifier An optional instance identifier
* @returns a function to unregister the callback
*/
onInit(callback, identifier) {
const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
const existingCallbacks = this.onInitCallbacks.get(normalizedIdentifier) ?? /* @__PURE__ */ new Set();
existingCallbacks.add(callback);
this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
const existingInstance = this.instances.get(normalizedIdentifier);
if (existingInstance) {
callback(existingInstance, normalizedIdentifier);
}
return () => {
existingCallbacks.delete(callback);
};
}
/**
* Invoke onInit callbacks synchronously
* @param instance the service instance`
*/
invokeOnInitCallbacks(instance, identifier) {
const callbacks = this.onInitCallbacks.get(identifier);
if (!callbacks) {
return;
}
for (const callback of callbacks) {
try {
callback(instance, identifier);
} catch {
}
}
}
getOrInitializeService({ instanceIdentifier, options = {} }) {
let instance = this.instances.get(instanceIdentifier);
if (!instance && this.component) {
instance = this.component.instanceFactory(this.container, {
instanceIdentifier: normalizeIdentifierForFactory2(instanceIdentifier),
options
});
this.instances.set(instanceIdentifier, instance);
this.instancesOptions.set(instanceIdentifier, options);
this.invokeOnInitCallbacks(instance, instanceIdentifier);
if (this.component.onInstanceCreated) {
try {
this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
} catch {
}
}
}
return instance || null;
}
normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME3) {
if (this.component) {
return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME3;
} else {
return identifier;
}
}
shouldAutoInitialize() {
return !!this.component && this.component.instantiationMode !== "EXPLICIT";
}
};
function normalizeIdentifierForFactory2(identifier) {
return identifier === DEFAULT_ENTRY_NAME3 ? void 0 : identifier;
}
function isComponentEager2(component) {
return component.instantiationMode === "EAGER";
}
var ComponentContainer2 = class {
constructor(name6) {
this.name = name6;
this.providers = /* @__PURE__ */ new Map();
}
/**
*
* @param component Component being added
* @param overwrite When a component with the same name has already been registered,
* if overwrite is true: overwrite the existing component with the new component and create a new
* provider with the new component. It can be useful in tests where you want to use different mocks
* for different tests.
* if overwrite is false: throw an exception
*/
addComponent(component) {
const provider = this.getProvider(component.name);
if (provider.isComponentSet()) {
throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
}
provider.setComponent(component);
}
addOrOverwriteComponent(component) {
const provider = this.getProvider(component.name);
if (provider.isComponentSet()) {
this.providers.delete(component.name);
}
this.addComponent(component);
}
/**
* getProvider provides a type safe interface where it can only be called with a field name
* present in NameServiceMapping interface.
*
* Firebase SDKs providing services should extend NameServiceMapping interface to register
* themselves.
*/
getProvider(name6) {
if (this.providers.has(name6)) {
return this.providers.get(name6);
}
const provider = new Provider2(name6, this);
this.providers.set(name6, provider);
return provider;
}
getProviders() {
return Array.from(this.providers.values());
}
};
exports2.Component = Component2;
exports2.ComponentContainer = ComponentContainer2;
exports2.Provider = Provider2;
}
});
// node_modules/@firebase/logger/dist/index.cjs.js
var require_index_cjs2 = __commonJS({
"node_modules/@firebase/logger/dist/index.cjs.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var instances2 = [];
exports2.LogLevel = void 0;
(function(LogLevel2) {
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
LogLevel2[LogLevel2["VERBOSE"] = 1] = "VERBOSE";
LogLevel2[LogLevel2["INFO"] = 2] = "INFO";
LogLevel2[LogLevel2["WARN"] = 3] = "WARN";
LogLevel2[LogLevel2["ERROR"] = 4] = "ERROR";
LogLevel2[LogLevel2["SILENT"] = 5] = "SILENT";
})(exports2.LogLevel || (exports2.LogLevel = {}));
var levelStringToEnum2 = {
"debug": exports2.LogLevel.DEBUG,
"verbose": exports2.LogLevel.VERBOSE,
"info": exports2.LogLevel.INFO,
"warn": exports2.LogLevel.WARN,
"error": exports2.LogLevel.ERROR,
"silent": exports2.LogLevel.SILENT
};
var defaultLogLevel2 = exports2.LogLevel.INFO;
var ConsoleMethod2 = {
[exports2.LogLevel.DEBUG]: "log",
[exports2.LogLevel.VERBOSE]: "log",
[exports2.LogLevel.INFO]: "info",
[exports2.LogLevel.WARN]: "warn",
[exports2.LogLevel.ERROR]: "error"
};
var defaultLogHandler2 = (instance, logType, ...args) => {
if (logType < instance.logLevel) {
return;
}
const now = (/* @__PURE__ */ new Date()).toISOString();
const method = ConsoleMethod2[logType];
if (method) {
console[method](`[${now}] ${instance.name}:`, ...args);
} else {
throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
}
};
var Logger2 = class {
/**
* Gives you an instance of a Logger to capture messages according to
* Firebase's logging scheme.
*
* @param name The name that the logs will be associated with
*/
constructor(name6) {
this.name = name6;
this._logLevel = defaultLogLevel2;
this._logHandler = defaultLogHandler2;
this._userLogHandler = null;
instances2.push(this);
}
get logLevel() {
return this._logLevel;
}
set logLevel(val) {
if (!(val in exports2.LogLevel)) {
throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
}
this._logLevel = val;
}
// Workaround for setter/getter having to be the same type.
setLogLevel(val) {
this._logLevel = typeof val === "string" ? levelStringToEnum2[val] : val;
}
get logHandler() {
return this._logHandler;
}
set logHandler(val) {
if (typeof val !== "function") {
throw new TypeError("Value assigned to `logHandler` must be a function");
}
this._logHandler = val;
}
get userLogHandler() {
return this._userLogHandler;
}
set userLogHandler(val) {
this._userLogHandler = val;
}
/**
* The functions below are all based on the `console` interface
*/
debug(...args) {
this._userLogHandler && this._userLogHandler(this, exports2.LogLevel.DEBUG, ...args);
this._logHandler(this, exports2.LogLevel.DEBUG, ...args);
}
log(...args) {
this._userLogHandler && this._userLogHandler(this, exports2.LogLevel.VERBOSE, ...args);
this._logHandler(this, exports2.LogLevel.VERBOSE, ...args);
}
info(...args) {
this._userLogHandler && this._userLogHandler(this, exports2.LogLevel.INFO, ...args);
this._logHandler(this, exports2.LogLevel.INFO, ...args);
}
warn(...args) {
this._userLogHandler && this._userLogHandler(this, exports2.LogLevel.WARN, ...args);
this._logHandler(this, exports2.LogLevel.WARN, ...args);
}
error(...args) {
this._userLogHandler && this._userLogHandler(this, exports2.LogLevel.ERROR, ...args);
this._logHandler(this, exports2.LogLevel.ERROR, ...args);
}
};
function setLogLevel2(level) {
instances2.forEach((inst) => {
inst.setLogLevel(level);
});
}
function setUserLogHandler2(logCallback, options) {
for (const instance of instances2) {
let customLogLevel = null;
if (options && options.level) {
customLogLevel = levelStringToEnum2[options.level];
}
if (logCallback === null) {
instance.userLogHandler = null;
} else {
instance.userLogHandler = (instance2, level, ...args) => {
const message = args.map((arg) => {
if (arg == null) {
return null;
} else if (typeof arg === "string") {
return arg;
} else if (typeof arg === "number" || typeof arg === "boolean") {
return arg.toString();
} else if (arg instanceof Error) {
return arg.message;
} else {
try {
return JSON.stringify(arg);
} catch (ignored) {
return null;
}
}
}).filter((arg) => arg).join(" ");
if (level >= (customLogLevel ?? instance2.logLevel)) {
logCallback({
level: exports2.LogLevel[level].toLowerCase(),
message,
args,
type: instance2.name
});
}
};
}
}
}
exports2.Logger = Logger2;
exports2.setLogLevel = setLogLevel2;
exports2.setUserLogHandler = setUserLogHandler2;
}
});
// node_modules/@firebase/app/dist/index.cjs.js
var require_index_cjs3 = __commonJS({
"node_modules/@firebase/app/dist/index.cjs.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var component = require_index_cjs();
var logger$1 = require_index_cjs2();
var util = require_index_node_cjs();
var idb = (init_build(), __toCommonJS(build_exports));
var PlatformLoggerServiceImpl2 = class {
constructor(container) {
this.container = container;
}
// In initial implementation, this will be called by installations on
// auth token refresh, and installations will send this string.
getPlatformInfoString() {
const providers = this.container.getProviders();
return providers.map((provider) => {
if (isVersionServiceProvider2(provider)) {
const service = provider.getImmediate();
return `${service.library}/${service.version}`;
} else {
return null;
}
}).filter((logString) => logString).join(" ");
}
};
function isVersionServiceProvider2(provider) {
const component2 = provider.getComponent();
return component2?.type === "VERSION";
}
var name$q2 = "@firebase/app";
var version$12 = "0.14.5";
var logger2 = new logger$1.Logger("@firebase/app");
var name$p2 = "@firebase/app-compat";
var name$o2 = "@firebase/analytics-compat";
var name$n2 = "@firebase/analytics";
var name$m2 = "@firebase/app-check-compat";
var name$l2 = "@firebase/app-check";
var name$k2 = "@firebase/auth";
var name$j2 = "@firebase/auth-compat";
var name$i2 = "@firebase/database";
var name$h2 = "@firebase/data-connect";
var name$g2 = "@firebase/database-compat";
var name$f2 = "@firebase/functions";
var name$e2 = "@firebase/functions-compat";
var name$d2 = "@firebase/installations";
var name$c2 = "@firebase/installations-compat";
var name$b2 = "@firebase/messaging";
var name$a2 = "@firebase/messaging-compat";
var name$92 = "@firebase/performance";
var name$82 = "@firebase/performance-compat";
var name$72 = "@firebase/remote-config";
var name$62 = "@firebase/remote-config-compat";
var name$52 = "@firebase/storage";
var name$42 = "@firebase/storage-compat";
var name$32 = "@firebase/firestore";
var name$22 = "@firebase/ai";
var name$12 = "@firebase/firestore-compat";
var name6 = "firebase";
var version6 = "12.5.0";
var DEFAULT_ENTRY_NAME3 = "[DEFAULT]";
var PLATFORM_LOG_STRING2 = {
[name$q2]: "fire-core",
[name$p2]: "fire-core-compat",
[name$n2]: "fire-analytics",
[name$o2]: "fire-analytics-compat",
[name$l2]: "fire-app-check",
[name$m2]: "fire-app-check-compat",
[name$k2]: "fire-auth",
[name$j2]: "fire-auth-compat",
[name$i2]: "fire-rtdb",
[name$h2]: "fire-data-connect",
[name$g2]: "fire-rtdb-compat",
[name$f2]: "fire-fn",
[name$e2]: "fire-fn-compat",
[name$d2]: "fire-iid",
[name$c2]: "fire-iid-compat",
[name$b2]: "fire-fcm",
[name$a2]: "fire-fcm-compat",
[name$92]: "fire-perf",
[name$82]: "fire-perf-compat",
[name$72]: "fire-rc",
[name$62]: "fire-rc-compat",
[name$52]: "fire-gcs",
[name$42]: "fire-gcs-compat",
[name$32]: "fire-fst",
[name$12]: "fire-fst-compat",
[name$22]: "fire-vertex",
"fire-js": "fire-js",
// Platform identifier for JS SDK.
[name6]: "fire-js-all"
};
var _apps2 = /* @__PURE__ */ new Map();
var _serverApps2 = /* @__PURE__ */ new Map();
var _components2 = /* @__PURE__ */ new Map();
function _addComponent2(app2, component2) {
try {
app2.container.addComponent(component2);
} catch (e) {
logger2.debug(`Component ${component2.name} failed to register with FirebaseApp ${app2.name}`, e);
}
}
function _addOrOverwriteComponent(app2, component2) {
app2.container.addOrOverwriteComponent(component2);
}
function _registerComponent2(component2) {
const componentName = component2.name;
if (_components2.has(componentName)) {
logger2.debug(`There were multiple attempts to register component ${componentName}.`);
return false;
}
_components2.set(componentName, component2);
for (const app2 of _apps2.values()) {
_addComponent2(app2, component2);
}
for (const serverApp of _serverApps2.values()) {
_addComponent2(serverApp, component2);
}
return true;
}
function _getProvider2(app2, name7) {
const heartbeatController = app2.container.getProvider("heartbeat").getImmediate({ optional: true });
if (heartbeatController) {
void heartbeatController.triggerHeartbeat();
}
return app2.container.getProvider(name7);
}
function _removeServiceInstance(app2, name7, instanceIdentifier = DEFAULT_ENTRY_NAME3) {
_getProvider2(app2, name7).clearInstance(instanceIdentifier);
}
function _isFirebaseApp(obj) {
return obj.options !== void 0;
}
function _isFirebaseServerAppSettings(obj) {
if (_isFirebaseApp(obj)) {
return false;
}
return "authIdToken" in obj || "appCheckToken" in obj || "releaseOnDeref" in obj || "automaticDataCollectionEnabled" in obj;
}
function _isFirebaseServerApp2(obj) {
if (obj === null || obj === void 0) {
return false;
}
return obj.settings !== void 0;
}
function _clearComponents() {
_components2.clear();
}
var ERRORS2 = {
[
"no-app"
/* AppError.NO_APP */
]: "No Firebase App '{$appName}' has been created - call initializeApp() first",
[
"bad-app-name"
/* AppError.BAD_APP_NAME */
]: "Illegal App name: '{$appName}'",
[
"duplicate-app"
/* AppError.DUPLICATE_APP */
]: "Firebase App named '{$appName}' already exists with different options or config",
[
"app-deleted"
/* AppError.APP_DELETED */
]: "Firebase App named '{$appName}' already deleted",
[
"server-app-deleted"
/* AppError.SERVER_APP_DELETED */
]: "Firebase Server App has been deleted",
[
"no-options"
/* AppError.NO_OPTIONS */
]: "Need to provide options, when not being deployed to hosting via source.",
[
"invalid-app-argument"
/* AppError.INVALID_APP_ARGUMENT */
]: "firebase.{$appName}() takes either no argument or a Firebase App instance.",
[
"invalid-log-argument"
/* AppError.INVALID_LOG_ARGUMENT */
]: "First argument to `onLog` must be null or a function.",
[
"idb-open"
/* AppError.IDB_OPEN */
]: "Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.",
[
"idb-get"
/* AppError.IDB_GET */
]: "Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.",
[
"idb-set"
/* AppError.IDB_WRITE */
]: "Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.",
[
"idb-delete"
/* AppError.IDB_DELETE */
]: "Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.",
[
"finalization-registry-not-supported"
/* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */
]: "FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.",
[
"invalid-server-app-environment"
/* AppError.INVALID_SERVER_APP_ENVIRONMENT */
]: "FirebaseServerApp is not for use in browser environments."
};
var ERROR_FACTORY2 = new util.ErrorFactory("app", "Firebase", ERRORS2);
var FirebaseAppImpl2 = class {
constructor(options, config, container) {
this._isDeleted = false;
this._options = { ...options };
this._config = { ...config };
this._name = config.name;
this._automaticDataCollectionEnabled = config.automaticDataCollectionEnabled;
this._container = container;
this.container.addComponent(new component.Component(
"app",
() => this,
"PUBLIC"
/* ComponentType.PUBLIC */
));
}
get automaticDataCollectionEnabled() {
this.checkDestroyed();
return this._automaticDataCollectionEnabled;
}
set automaticDataCollectionEnabled(val) {
this.checkDestroyed();
this._automaticDataCollectionEnabled = val;
}
get name() {
this.checkDestroyed();
return this._name;
}
get options() {
this.checkDestroyed();
return this._options;
}
get config() {
this.checkDestroyed();
return this._config;
}
get container() {
return this._container;
}
get isDeleted() {
return this._isDeleted;
}
set isDeleted(val) {
this._isDeleted = val;
}
/**
* This function will throw an Error if the App has already been deleted -
* use before performing API actions on the App.
*/
checkDestroyed() {
if (this.isDeleted) {
throw ERROR_FACTORY2.create("app-deleted", { appName: this._name });
}
}
};
function validateTokenTTL(base64Token, tokenName) {
const secondPart = util.base64Decode(base64Token.split(".")[1]);
if (secondPart === null) {
console.error(`FirebaseServerApp ${tokenName} is invalid: second part could not be parsed.`);
return;
}
const expClaim = JSON.parse(secondPart).exp;
if (expClaim === void 0) {
console.error(`FirebaseServerApp ${tokenName} is invalid: expiration claim could not be parsed`);
return;
}
const exp = JSON.parse(secondPart).exp * 1e3;
const now = (/* @__PURE__ */ new Date()).getTime();
const diff = exp - now;
if (diff <= 0) {
console.error(`FirebaseServerApp ${tokenName} is invalid: the token has expired.`);
}
}
var FirebaseServerAppImpl = class extends FirebaseAppImpl2 {
constructor(options, serverConfig, name7, container) {
const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== void 0 ? serverConfig.automaticDataCollectionEnabled : true;
const config = {
name: name7,
automaticDataCollectionEnabled
};
if (options.apiKey !== void 0) {
super(options, config, container);
} else {
const appImpl = options;
super(appImpl.options, config, container);
}
this._serverConfig = {
automaticDataCollectionEnabled,
...serverConfig
};
if (this._serverConfig.authIdToken) {
validateTokenTTL(this._serverConfig.authIdToken, "authIdToken");
}
if (this._serverConfig.appCheckToken) {
validateTokenTTL(this._serverConfig.appCheckToken, "appCheckToken");
}
this._finalizationRegistry = null;
if (typeof FinalizationRegistry !== "undefined") {
this._finalizationRegistry = new FinalizationRegistry(() => {
this.automaticCleanup();
});
}
this._refCount = 0;
this.incRefCount(this._serverConfig.releaseOnDeref);
this._serverConfig.releaseOnDeref = void 0;
serverConfig.releaseOnDeref = void 0;
registerVersion2(name$q2, version$12, "serverapp");
}
toJSON() {
return void 0;
}
get refCount() {
return this._refCount;
}
// Increment the reference count of this server app. If an object is provided, register it
// with the finalization registry.
incRefCount(obj) {
if (this.isDeleted) {
return;
}
this._refCount++;
if (obj !== void 0 && this._finalizationRegistry !== null) {
this._finalizationRegistry.register(obj, this);
}
}
// Decrement the reference count.
decRefCount() {
if (this.isDeleted) {
return 0;
}
return --this._refCount;
}
// Invoked by the FinalizationRegistry callback to note that this app should go through its
// reference counts and delete itself if no reference count remain. The coordinating logic that
// handles this is in deleteApp(...).
automaticCleanup() {
void deleteApp(this);
}
get settings() {
this.checkDestroyed();
return this._serverConfig;
}
/**
* This function will throw an Error if the App has already been deleted -
* use before performing API actions on the App.
*/
checkDestroyed() {
if (this.isDeleted) {
throw ERROR_FACTORY2.create(
"server-app-deleted"
/* AppError.SERVER_APP_DELETED */
);
}
}
};
var SDK_VERSION2 = version6;
function initializeApp2(_options, rawConfig = {}) {
let options = _options;
if (typeof rawConfig !== "object") {
const name8 = rawConfig;
rawConfig = { name: name8 };
}
const config = {
name: DEFAULT_ENTRY_NAME3,
automaticDataCollectionEnabled: true,
...rawConfig
};
const name7 = config.name;
if (typeof name7 !== "string" || !name7) {
throw ERROR_FACTORY2.create("bad-app-name", {
appName: String(name7)
});
}
options || (options = util.getDefaultAppConfig());
if (!options) {
throw ERROR_FACTORY2.create(
"no-options"
/* AppError.NO_OPTIONS */
);
}
const existingApp = _apps2.get(name7);
if (existingApp) {
if (util.deepEqual(options, existingApp.options) && util.deepEqual(config, existingApp.config)) {
return existingApp;
} else {
throw ERROR_FACTORY2.create("duplicate-app", { appName: name7 });
}
}
const container = new component.ComponentContainer(name7);
for (const component2 of _components2.values()) {
container.addComponent(component2);
}
const newApp = new FirebaseAppImpl2(options, config, container);
_apps2.set(name7, newApp);
return newApp;
}
function initializeServerApp(_options, _serverAppConfig = {}) {
if (util.isBrowser() && !util.isWebWorker()) {
throw ERROR_FACTORY2.create(
"invalid-server-app-environment"
/* AppError.INVALID_SERVER_APP_ENVIRONMENT */
);
}
let firebaseOptions;
let serverAppSettings = _serverAppConfig || {};
if (_options) {
if (_isFirebaseApp(_options)) {
firebaseOptions = _options.options;
} else if (_isFirebaseServerAppSettings(_options)) {
serverAppSettings = _options;
} else {
firebaseOptions = _options;
}
}
if (serverAppSettings.automaticDataCollectionEnabled === void 0) {
serverAppSettings.automaticDataCollectionEnabled = true;
}
firebaseOptions || (firebaseOptions = util.getDefaultAppConfig());
if (!firebaseOptions) {
throw ERROR_FACTORY2.create(
"no-options"
/* AppError.NO_OPTIONS */
);
}
const nameObj = {
...serverAppSettings,
...firebaseOptions
};
if (nameObj.releaseOnDeref !== void 0) {
delete nameObj.releaseOnDeref;
}
const hashCode = (s) => {
return [...s].reduce((hash, c) => Math.imul(31, hash) + c.charCodeAt(0) | 0, 0);
};
if (serverAppSettings.releaseOnDeref !== void 0) {
if (typeof FinalizationRegistry === "undefined") {
throw ERROR_FACTORY2.create("finalization-registry-not-supported", {});
}
}
const nameString = "" + hashCode(JSON.stringify(nameObj));
const existingApp = _serverApps2.get(nameString);
if (existingApp) {
existingApp.incRefCount(serverAppSettings.releaseOnDeref);
return existingApp;
}
const container = new component.ComponentContainer(nameString);
for (const component2 of _components2.values()) {
container.addComponent(component2);
}
const newApp = new FirebaseServerAppImpl(firebaseOptions, serverAppSettings, nameString, container);
_serverApps2.set(nameString, newApp);
return newApp;
}
function getApp2(name7 = DEFAULT_ENTRY_NAME3) {
const app2 = _apps2.get(name7);
if (!app2 && name7 === DEFAULT_ENTRY_NAME3 && util.getDefaultAppConfig()) {
return initializeApp2();
}
if (!app2) {
throw ERROR_FACTORY2.create("no-app", { appName: name7 });
}
return app2;
}
function getApps() {
return Array.from(_apps2.values());
}
async function deleteApp(app2) {
let cleanupProviders = false;
const name7 = app2.name;
if (_apps2.has(name7)) {
cleanupProviders = true;
_apps2.delete(name7);
} else if (_serverApps2.has(name7)) {
const firebaseServerApp = app2;
if (firebaseServerApp.decRefCount() <= 0) {
_serverApps2.delete(name7);
cleanupProviders = true;
}
}
if (cleanupProviders) {
await Promise.all(app2.container.getProviders().map((provider) => provider.delete()));
app2.isDeleted = true;
}
}
function registerVersion2(libraryKeyOrName, version7, variant) {
let library = PLATFORM_LOG_STRING2[libraryKeyOrName] ?? libraryKeyOrName;
if (variant) {
library += `-${variant}`;
}
const libraryMismatch = library.match(/\s|\//);
const versionMismatch = version7.match(/\s|\//);
if (libraryMismatch || versionMismatch) {
const warning = [
`Unable to register library "${library}" with version "${version7}":`
];
if (libraryMismatch) {
warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
}
if (libraryMismatch && versionMismatch) {
warning.push("and");
}
if (versionMismatch) {
warning.push(`version name "${version7}" contains illegal characters (whitespace or "/")`);
}
logger2.warn(warning.join(" "));
return;
}
_registerComponent2(new component.Component(
`${library}-version`,
() => ({ library, version: version7 }),
"VERSION"
/* ComponentType.VERSION */
));
}
function onLog(logCallback, options) {
if (logCallback !== null && typeof logCallback !== "function") {
throw ERROR_FACTORY2.create(
"invalid-log-argument"
/* AppError.INVALID_LOG_ARGUMENT */
);
}
logger$1.setUserLogHandler(logCallback, options);
}
function setLogLevel2(logLevel) {
logger$1.setLogLevel(logLevel);
}
var DB_NAME2 = "firebase-heartbeat-database";
var DB_VERSION2 = 1;
var STORE_NAME2 = "firebase-heartbeat-store";
var dbPromise2 = null;
function getDbPromise2() {
if (!dbPromise2) {
dbPromise2 = idb.openDB(DB_NAME2, DB_VERSION2, {
upgrade: (db, oldVersion) => {
switch (oldVersion) {
case 0:
try {
db.createObjectStore(STORE_NAME2);
} catch (e) {
console.warn(e);
}
}
}
}).catch((e) => {
throw ERROR_FACTORY2.create("idb-open", {
originalErrorMessage: e.message
});
});
}
return dbPromise2;
}
async function readHeartbeatsFromIndexedDB2(app2) {
try {
const db = await getDbPromise2();
const tx = db.transaction(STORE_NAME2);
const result = await tx.objectStore(STORE_NAME2).get(computeKey2(app2));
await tx.done;
return result;
} catch (e) {
if (e instanceof util.FirebaseError) {
logger2.warn(e.message);
} else {
const idbGetError = ERROR_FACTORY2.create("idb-get", {
originalErrorMessage: e?.message
});
logger2.warn(idbGetError.message);
}
}
}
async function writeHeartbeatsToIndexedDB2(app2, heartbeatObject) {
try {
const db = await getDbPromise2();
const tx = db.transaction(STORE_NAME2, "readwrite");
const objectStore = tx.objectStore(STORE_NAME2);
await objectStore.put(heartbeatObject, computeKey2(app2));
await tx.done;
} catch (e) {
if (e instanceof util.FirebaseError) {
logger2.warn(e.message);
} else {
const idbGetError = ERROR_FACTORY2.create("idb-set", {
originalErrorMessage: e?.message
});
logger2.warn(idbGetError.message);
}
}
}
function computeKey2(app2) {
return `${app2.name}!${app2.options.appId}`;
}
var MAX_HEADER_BYTES2 = 1024;
var MAX_NUM_STORED_HEARTBEATS2 = 30;
var HeartbeatServiceImpl2 = class {
constructor(container) {
this.container = container;
this._heartbeatsCache = null;
const app2 = this.container.getProvider("app").getImmediate();
this._storage = new HeartbeatStorageImpl2(app2);
this._heartbeatsCachePromise = this._storage.read().then((result) => {
this._heartbeatsCache = result;
return result;
});
}
/**
* Called to report a heartbeat. The function will generate
* a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
* to IndexedDB.
* Note that we only store one heartbeat per day. So if a heartbeat for today is
* already logged, subsequent calls to this function in the same day will be ignored.
*/
async triggerHeartbeat() {
try {
const platformLogger = this.container.getProvider("platform-logger").getImmediate();
const agent = platformLogger.getPlatformInfoString();
const date = getUTCDateString2();
if (this._heartbeatsCache?.heartbeats == null) {
this._heartbeatsCache = await this._heartbeatsCachePromise;
if (this._heartbeatsCache?.heartbeats == null) {
return;
}
}
if (this._heartbeatsCache.lastSentHeartbeatDate === date || this._heartbeatsCache.heartbeats.some((singleDateHeartbeat) => singleDateHeartbeat.date === date)) {
return;
} else {
this._heartbeatsCache.heartbeats.push({ date, agent });
if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS2) {
const earliestHeartbeatIdx = getEarliestHeartbeatIdx2(this._heartbeatsCache.heartbeats);
this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1);
}
}
return this._storage.overwrite(this._heartbeatsCache);
} catch (e) {
logger2.warn(e);
}
}
/**
* Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
* It also clears all heartbeats from memory as well as in IndexedDB.
*
* NOTE: Consuming product SDKs should not send the header if this method
* returns an empty string.
*/
async getHeartbeatsHeader() {
try {
if (this._heartbeatsCache === null) {
await this._heartbeatsCachePromise;
}
if (this._heartbeatsCache?.heartbeats == null || this._heartbeatsCache.heartbeats.length === 0) {
return "";
}
const date = getUTCDateString2();
const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader2(this._heartbeatsCache.heartbeats);
const headerString = util.base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
this._heartbeatsCache.lastSentHeartbeatDate = date;
if (unsentEntries.length > 0) {
this._heartbeatsCache.heartbeats = unsentEntries;
await this._storage.overwrite(this._heartbeatsCache);
} else {
this._heartbeatsCache.heartbeats = [];
void this._storage.overwrite(this._heartbeatsCache);
}
return headerString;
} catch (e) {
logger2.warn(e);
return "";
}
}
};
function getUTCDateString2() {
const today = /* @__PURE__ */ new Date();
return today.toISOString().substring(0, 10);
}
function extractHeartbeatsForHeader2(heartbeatsCache, maxSize = MAX_HEADER_BYTES2) {
const heartbeatsToSend = [];
let unsentEntries = heartbeatsCache.slice();
for (const singleDateHeartbeat of heartbeatsCache) {
const heartbeatEntry = heartbeatsToSend.find((hb) => hb.agent === singleDateHeartbeat.agent);
if (!heartbeatEntry) {
heartbeatsToSend.push({
agent: singleDateHeartbeat.agent,
dates: [singleDateHeartbeat.date]
});
if (countBytes2(heartbeatsToSend) > maxSize) {
heartbeatsToSend.pop();
break;
}
} else {
heartbeatEntry.dates.push(singleDateHeartbeat.date);
if (countBytes2(heartbeatsToSend) > maxSize) {
heartbeatEntry.dates.pop();
break;
}
}
unsentEntries = unsentEntries.slice(1);
}
return {
heartbeatsToSend,
unsentEntries
};
}
var HeartbeatStorageImpl2 = class {
constructor(app2) {
this.app = app2;
this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
}
async runIndexedDBEnvironmentCheck() {
if (!util.isIndexedDBAvailable()) {
return false;
} else {
return util.validateIndexedDBOpenable().then(() => true).catch(() => false);
}
}
/**
* Read all heartbeats.
*/
async read() {
const canUseIndexedDB = await this._canUseIndexedDBPromise;
if (!canUseIndexedDB) {
return { heartbeats: [] };
} else {
const idbHeartbeatObject = await readHeartbeatsFromIndexedDB2(this.app);
if (idbHeartbeatObject?.heartbeats) {
return idbHeartbeatObject;
} else {
return { heartbeats: [] };
}
}
}
// overwrite the storage with the provided heartbeats
async overwrite(heartbeatsObject) {
const canUseIndexedDB = await this._canUseIndexedDBPromise;
if (!canUseIndexedDB) {
return;
} else {
const existingHeartbeatsObject = await this.read();
return writeHeartbeatsToIndexedDB2(this.app, {
lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ?? existingHeartbeatsObject.lastSentHeartbeatDate,
heartbeats: heartbeatsObject.heartbeats
});
}
}
// add heartbeats
async add(heartbeatsObject) {
const canUseIndexedDB = await this._canUseIndexedDBPromise;
if (!canUseIndexedDB) {
return;
} else {
const existingHeartbeatsObject = await this.read();
return writeHeartbeatsToIndexedDB2(this.app, {
lastSentHeartbeatDate: heartbeatsObject.lastSentHeartbeatDate ?? existingHeartbeatsObject.lastSentHeartbeatDate,
heartbeats: [
...existingHeartbeatsObject.heartbeats,
...heartbeatsObject.heartbeats
]
});
}
}
};
function countBytes2(heartbeatsCache) {
return util.base64urlEncodeWithoutPadding(
// heartbeatsCache wrapper properties
JSON.stringify({ version: 2, heartbeats: heartbeatsCache })
).length;
}
function getEarliestHeartbeatIdx2(heartbeats) {
if (heartbeats.length === 0) {
return -1;
}
let earliestHeartbeatIdx = 0;
let earliestHeartbeatDate = heartbeats[0].date;
for (let i = 1; i < heartbeats.length; i++) {
if (heartbeats[i].date < earliestHeartbeatDate) {
earliestHeartbeatDate = heartbeats[i].date;
earliestHeartbeatIdx = i;
}
}
return earliestHeartbeatIdx;
}
function registerCoreComponents2(variant) {
_registerComponent2(new component.Component(
"platform-logger",
(container) => new PlatformLoggerServiceImpl2(container),
"PRIVATE"
/* ComponentType.PRIVATE */
));
_registerComponent2(new component.Component(
"heartbeat",
(container) => new HeartbeatServiceImpl2(container),
"PRIVATE"
/* ComponentType.PRIVATE */
));
registerVersion2(name$q2, version$12, variant);
registerVersion2(name$q2, version$12, "cjs2020");
registerVersion2("fire-js", "");
}
registerCoreComponents2("node");
Object.defineProperty(exports2, "FirebaseError", {
enumerable: true,
get: function() {
return util.FirebaseError;
}
});
exports2.SDK_VERSION = SDK_VERSION2;
exports2._DEFAULT_ENTRY_NAME = DEFAULT_ENTRY_NAME3;
exports2._addComponent = _addComponent2;
exports2._addOrOverwriteComponent = _addOrOverwriteComponent;
exports2._apps = _apps2;
exports2._clearComponents = _clearComponents;
exports2._components = _components2;
exports2._getProvider = _getProvider2;
exports2._isFirebaseApp = _isFirebaseApp;
exports2._isFirebaseServerApp = _isFirebaseServerApp2;
exports2._isFirebaseServerAppSettings = _isFirebaseServerAppSettings;
exports2._registerComponent = _registerComponent2;
exports2._removeServiceInstance = _removeServiceInstance;
exports2._serverApps = _serverApps2;
exports2.deleteApp = deleteApp;
exports2.getApp = getApp2;
exports2.getApps = getApps;
exports2.initializeApp = initializeApp2;
exports2.initializeServerApp = initializeServerApp;
exports2.onLog = onLog;
exports2.registerVersion = registerVersion2;
exports2.setLogLevel = setLogLevel2;
}
});
// node_modules/@firebase/auth/dist/node/totp-50d5d5dd.js
var require_totp_50d5d5dd = __commonJS({
"node_modules/@firebase/auth/dist/node/totp-50d5d5dd.js"(exports2) {
"use strict";
var app2 = require_index_cjs3();
var util = require_index_node_cjs();
var component = require_index_cjs();
var logger2 = require_index_cjs2();
var FactorId2 = {
/** Phone as second factor */
PHONE: "phone",
TOTP: "totp"
};
var ProviderId2 = {
/** Facebook provider ID */
FACEBOOK: "facebook.com",
/** GitHub provider ID */
GITHUB: "github.com",
/** Google provider ID */
GOOGLE: "google.com",
/** Password provider */
PASSWORD: "password",
/** Phone provider */
PHONE: "phone",
/** Twitter provider ID */
TWITTER: "twitter.com"
};
var SignInMethod2 = {
/** Email link sign in method */
EMAIL_LINK: "emailLink",
/** Email/password sign in method */
EMAIL_PASSWORD: "password",
/** Facebook sign in method */
FACEBOOK: "facebook.com",
/** GitHub sign in method */
GITHUB: "github.com",
/** Google sign in method */
GOOGLE: "google.com",
/** Phone sign in method */
PHONE: "phone",
/** Twitter sign in method */
TWITTER: "twitter.com"
};
var OperationType2 = {
/** Operation involving linking an additional provider to an already signed-in user. */
LINK: "link",
/** Operation involving using a provider to reauthenticate an already signed-in user. */
REAUTHENTICATE: "reauthenticate",
/** Operation involving signing in a user. */
SIGN_IN: "signIn"
};
var ActionCodeOperation2 = {
/** The email link sign-in action. */
EMAIL_SIGNIN: "EMAIL_SIGNIN",
/** The password reset action. */
PASSWORD_RESET: "PASSWORD_RESET",
/** The email revocation action. */
RECOVER_EMAIL: "RECOVER_EMAIL",
/** The revert second factor addition email action. */
REVERT_SECOND_FACTOR_ADDITION: "REVERT_SECOND_FACTOR_ADDITION",
/** The revert second factor addition email action. */
VERIFY_AND_CHANGE_EMAIL: "VERIFY_AND_CHANGE_EMAIL",
/** The email verification action. */
VERIFY_EMAIL: "VERIFY_EMAIL"
};
function _debugErrorMap2() {
return {
[
"admin-restricted-operation"
/* AuthErrorCode.ADMIN_ONLY_OPERATION */
]: "This operation is restricted to administrators only.",
[
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
]: "",
[
"app-not-authorized"
/* AuthErrorCode.APP_NOT_AUTHORIZED */
]: "This app, identified by the domain where it's hosted, is not authorized to use Firebase Authentication with the provided API key. Review your key configuration in the Google API console.",
[
"app-not-installed"
/* AuthErrorCode.APP_NOT_INSTALLED */
]: "The requested mobile application corresponding to the identifier (Android package name or iOS bundle ID) provided is not installed on this device.",
[
"captcha-check-failed"
/* AuthErrorCode.CAPTCHA_CHECK_FAILED */
]: "The reCAPTCHA response token provided is either invalid, expired, already used or the domain associated with it does not match the list of whitelisted domains.",
[
"code-expired"
/* AuthErrorCode.CODE_EXPIRED */
]: "The SMS code has expired. Please re-send the verification code to try again.",
[
"cordova-not-ready"
/* AuthErrorCode.CORDOVA_NOT_READY */
]: "Cordova framework is not ready.",
[
"cors-unsupported"
/* AuthErrorCode.CORS_UNSUPPORTED */
]: "This browser is not supported.",
[
"credential-already-in-use"
/* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */
]: "This credential is already associated with a different user account.",
[
"custom-token-mismatch"
/* AuthErrorCode.CREDENTIAL_MISMATCH */
]: "The custom token corresponds to a different audience.",
[
"requires-recent-login"
/* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
]: "This operation is sensitive and requires recent authentication. Log in again before retrying this request.",
[
"dependent-sdk-initialized-before-auth"
/* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
]: "Another Firebase SDK was initialized and is trying to use Auth before Auth is initialized. Please be sure to call `initializeAuth` or `getAuth` before starting any other Firebase SDK.",
[
"dynamic-link-not-activated"
/* AuthErrorCode.DYNAMIC_LINK_NOT_ACTIVATED */
]: "Please activate Dynamic Links in the Firebase Console and agree to the terms and conditions.",
[
"email-change-needs-verification"
/* AuthErrorCode.EMAIL_CHANGE_NEEDS_VERIFICATION */
]: "Multi-factor users must always have a verified email.",
[
"email-already-in-use"
/* AuthErrorCode.EMAIL_EXISTS */
]: "The email address is already in use by another account.",
[
"emulator-config-failed"
/* AuthErrorCode.EMULATOR_CONFIG_FAILED */
]: 'Auth instance has already been used to make a network call. Auth can no longer be configured to use the emulator. Try calling "connectAuthEmulator()" sooner.',
[
"expired-action-code"
/* AuthErrorCode.EXPIRED_OOB_CODE */
]: "The action code has expired.",
[
"cancelled-popup-request"
/* AuthErrorCode.EXPIRED_POPUP_REQUEST */
]: "This operation has been cancelled due to another conflicting popup being opened.",
[
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
]: "An internal AuthError has occurred.",
[
"invalid-app-credential"
/* AuthErrorCode.INVALID_APP_CREDENTIAL */
]: "The phone verification request contains an invalid application verifier. The reCAPTCHA token response is either invalid or expired.",
[
"invalid-app-id"
/* AuthErrorCode.INVALID_APP_ID */
]: "The mobile app identifier is not registered for the current project.",
[
"invalid-user-token"
/* AuthErrorCode.INVALID_AUTH */
]: "This user's credential isn't valid for this project. This can happen if the user's token has been tampered with, or if the user isn't for the project associated with this API key.",
[
"invalid-auth-event"
/* AuthErrorCode.INVALID_AUTH_EVENT */
]: "An internal AuthError has occurred.",
[
"invalid-verification-code"
/* AuthErrorCode.INVALID_CODE */
]: "The SMS verification code used to create the phone auth credential is invalid. Please resend the verification code sms and be sure to use the verification code provided by the user.",
[
"invalid-continue-uri"
/* AuthErrorCode.INVALID_CONTINUE_URI */
]: "The continue URL provided in the request is invalid.",
[
"invalid-cordova-configuration"
/* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */
]: "The following Cordova plugins must be installed to enable OAuth sign-in: cordova-plugin-buildinfo, cordova-universal-links-plugin, cordova-plugin-browsertab, cordova-plugin-inappbrowser and cordova-plugin-customurlscheme.",
[
"invalid-custom-token"
/* AuthErrorCode.INVALID_CUSTOM_TOKEN */
]: "The custom token format is incorrect. Please check the documentation.",
[
"invalid-dynamic-link-domain"
/* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */
]: "The provided dynamic link domain is not configured or authorized for the current project.",
[
"invalid-email"
/* AuthErrorCode.INVALID_EMAIL */
]: "The email address is badly formatted.",
[
"invalid-emulator-scheme"
/* AuthErrorCode.INVALID_EMULATOR_SCHEME */
]: "Emulator URL must start with a valid scheme (http:// or https://).",
[
"invalid-api-key"
/* AuthErrorCode.INVALID_API_KEY */
]: "Your API key is invalid, please check you have copied it correctly.",
[
"invalid-cert-hash"
/* AuthErrorCode.INVALID_CERT_HASH */
]: "The SHA-1 certificate hash provided is invalid.",
[
"invalid-credential"
/* AuthErrorCode.INVALID_CREDENTIAL */
]: "The supplied auth credential is incorrect, malformed or has expired.",
[
"invalid-message-payload"
/* AuthErrorCode.INVALID_MESSAGE_PAYLOAD */
]: "The email template corresponding to this action contains invalid characters in its message. Please fix by going to the Auth email templates section in the Firebase Console.",
[
"invalid-multi-factor-session"
/* AuthErrorCode.INVALID_MFA_SESSION */
]: "The request does not contain a valid proof of first factor successful sign-in.",
[
"invalid-oauth-provider"
/* AuthErrorCode.INVALID_OAUTH_PROVIDER */
]: "EmailAuthProvider is not supported for this operation. This operation only supports OAuth providers.",
[
"invalid-oauth-client-id"
/* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */
]: "The OAuth client ID provided is either invalid or does not match the specified API key.",
[
"unauthorized-domain"
/* AuthErrorCode.INVALID_ORIGIN */
]: "This domain is not authorized for OAuth operations for your Firebase project. Edit the list of authorized domains from the Firebase console.",
[
"invalid-action-code"
/* AuthErrorCode.INVALID_OOB_CODE */
]: "The action code is invalid. This can happen if the code is malformed, expired, or has already been used.",
[
"wrong-password"
/* AuthErrorCode.INVALID_PASSWORD */
]: "The password is invalid or the user does not have a password.",
[
"invalid-persistence-type"
/* AuthErrorCode.INVALID_PERSISTENCE */
]: "The specified persistence type is invalid. It can only be local, session or none.",
[
"invalid-phone-number"
/* AuthErrorCode.INVALID_PHONE_NUMBER */
]: "The format of the phone number provided is incorrect. Please enter the phone number in a format that can be parsed into E.164 format. E.164 phone numbers are written in the format [+][country code][subscriber number including area code].",
[
"invalid-provider-id"
/* AuthErrorCode.INVALID_PROVIDER_ID */
]: "The specified provider ID is invalid.",
[
"invalid-recipient-email"
/* AuthErrorCode.INVALID_RECIPIENT_EMAIL */
]: "The email corresponding to this action failed to send as the provided recipient email address is invalid.",
[
"invalid-sender"
/* AuthErrorCode.INVALID_SENDER */
]: "The email template corresponding to this action contains an invalid sender email or name. Please fix by going to the Auth email templates section in the Firebase Console.",
[
"invalid-verification-id"
/* AuthErrorCode.INVALID_SESSION_INFO */
]: "The verification ID used to create the phone auth credential is invalid.",
[
"invalid-tenant-id"
/* AuthErrorCode.INVALID_TENANT_ID */
]: "The Auth instance's tenant ID is invalid.",
[
"login-blocked"
/* AuthErrorCode.LOGIN_BLOCKED */
]: "Login blocked by user-provided method: {$originalMessage}",
[
"missing-android-pkg-name"
/* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
]: "An Android Package Name must be provided if the Android App is required to be installed.",
[
"auth-domain-config-required"
/* AuthErrorCode.MISSING_AUTH_DOMAIN */
]: "Be sure to include authDomain when calling firebase.initializeApp(), by following the instructions in the Firebase console.",
[
"missing-app-credential"
/* AuthErrorCode.MISSING_APP_CREDENTIAL */
]: "The phone verification request is missing an application verifier assertion. A reCAPTCHA response token needs to be provided.",
[
"missing-verification-code"
/* AuthErrorCode.MISSING_CODE */
]: "The phone auth credential was created with an empty SMS verification code.",
[
"missing-continue-uri"
/* AuthErrorCode.MISSING_CONTINUE_URI */
]: "A continue URL must be provided in the request.",
[
"missing-iframe-start"
/* AuthErrorCode.MISSING_IFRAME_START */
]: "An internal AuthError has occurred.",
[
"missing-ios-bundle-id"
/* AuthErrorCode.MISSING_IOS_BUNDLE_ID */
]: "An iOS Bundle ID must be provided if an App Store ID is provided.",
[
"missing-or-invalid-nonce"
/* AuthErrorCode.MISSING_OR_INVALID_NONCE */
]: "The request does not contain a valid nonce. This can occur if the SHA-256 hash of the provided raw nonce does not match the hashed nonce in the ID token payload.",
[
"missing-password"
/* AuthErrorCode.MISSING_PASSWORD */
]: "A non-empty password must be provided",
[
"missing-multi-factor-info"
/* AuthErrorCode.MISSING_MFA_INFO */
]: "No second factor identifier is provided.",
[
"missing-multi-factor-session"
/* AuthErrorCode.MISSING_MFA_SESSION */
]: "The request is missing proof of first factor successful sign-in.",
[
"missing-phone-number"
/* AuthErrorCode.MISSING_PHONE_NUMBER */
]: "To send verification codes, provide a phone number for the recipient.",
[
"missing-verification-id"
/* AuthErrorCode.MISSING_SESSION_INFO */
]: "The phone auth credential was created with an empty verification ID.",
[
"app-deleted"
/* AuthErrorCode.MODULE_DESTROYED */
]: "This instance of FirebaseApp has been deleted.",
[
"multi-factor-info-not-found"
/* AuthErrorCode.MFA_INFO_NOT_FOUND */
]: "The user does not have a second factor matching the identifier provided.",
[
"multi-factor-auth-required"
/* AuthErrorCode.MFA_REQUIRED */
]: "Proof of ownership of a second factor is required to complete sign-in.",
[
"account-exists-with-different-credential"
/* AuthErrorCode.NEED_CONFIRMATION */
]: "An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.",
[
"network-request-failed"
/* AuthErrorCode.NETWORK_REQUEST_FAILED */
]: "A network AuthError (such as timeout, interrupted connection or unreachable host) has occurred.",
[
"no-auth-event"
/* AuthErrorCode.NO_AUTH_EVENT */
]: "An internal AuthError has occurred.",
[
"no-such-provider"
/* AuthErrorCode.NO_SUCH_PROVIDER */
]: "User was not linked to an account with the given provider.",
[
"null-user"
/* AuthErrorCode.NULL_USER */
]: "A null user object was provided as the argument for an operation which requires a non-null user object.",
[
"operation-not-allowed"
/* AuthErrorCode.OPERATION_NOT_ALLOWED */
]: "The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section.",
[
"operation-not-supported-in-this-environment"
/* AuthErrorCode.OPERATION_NOT_SUPPORTED */
]: 'This operation is not supported in the environment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled.',
[
"popup-blocked"
/* AuthErrorCode.POPUP_BLOCKED */
]: "Unable to establish a connection with the popup. It may have been blocked by the browser.",
[
"popup-closed-by-user"
/* AuthErrorCode.POPUP_CLOSED_BY_USER */
]: "The popup has been closed by the user before finalizing the operation.",
[
"provider-already-linked"
/* AuthErrorCode.PROVIDER_ALREADY_LINKED */
]: "User can only be linked to one identity for the given provider.",
[
"quota-exceeded"
/* AuthErrorCode.QUOTA_EXCEEDED */
]: "The project's quota for this operation has been exceeded.",
[
"redirect-cancelled-by-user"
/* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */
]: "The redirect operation has been cancelled by the user before finalizing.",
[
"redirect-operation-pending"
/* AuthErrorCode.REDIRECT_OPERATION_PENDING */
]: "A redirect sign-in operation is already pending.",
[
"rejected-credential"
/* AuthErrorCode.REJECTED_CREDENTIAL */
]: "The request contains malformed or mismatching credentials.",
[
"second-factor-already-in-use"
/* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */
]: "The second factor is already enrolled on this account.",
[
"maximum-second-factor-count-exceeded"
/* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */
]: "The maximum allowed number of second factors on a user has been exceeded.",
[
"tenant-id-mismatch"
/* AuthErrorCode.TENANT_ID_MISMATCH */
]: "The provided tenant ID does not match the Auth instance's tenant ID",
[
"timeout"
/* AuthErrorCode.TIMEOUT */
]: "The operation has timed out.",
[
"user-token-expired"
/* AuthErrorCode.TOKEN_EXPIRED */
]: "The user's credential is no longer valid. The user must sign in again.",
[
"too-many-requests"
/* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */
]: "We have blocked all requests from this device due to unusual activity. Try again later.",
[
"unauthorized-continue-uri"
/* AuthErrorCode.UNAUTHORIZED_DOMAIN */
]: "The domain of the continue URL is not whitelisted. Please whitelist the domain in the Firebase console.",
[
"unsupported-first-factor"
/* AuthErrorCode.UNSUPPORTED_FIRST_FACTOR */
]: "Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.",
[
"unsupported-persistence-type"
/* AuthErrorCode.UNSUPPORTED_PERSISTENCE */
]: "The current environment does not support the specified persistence type.",
[
"unsupported-tenant-operation"
/* AuthErrorCode.UNSUPPORTED_TENANT_OPERATION */
]: "This operation is not supported in a multi-tenant context.",
[
"unverified-email"
/* AuthErrorCode.UNVERIFIED_EMAIL */
]: "The operation requires a verified email.",
[
"user-cancelled"
/* AuthErrorCode.USER_CANCELLED */
]: "The user did not grant your application the permissions it requested.",
[
"user-not-found"
/* AuthErrorCode.USER_DELETED */
]: "There is no user record corresponding to this identifier. The user may have been deleted.",
[
"user-disabled"
/* AuthErrorCode.USER_DISABLED */
]: "The user account has been disabled by an administrator.",
[
"user-mismatch"
/* AuthErrorCode.USER_MISMATCH */
]: "The supplied credentials do not correspond to the previously signed in user.",
[
"user-signed-out"
/* AuthErrorCode.USER_SIGNED_OUT */
]: "",
[
"weak-password"
/* AuthErrorCode.WEAK_PASSWORD */
]: "The password must be 6 characters long or more.",
[
"web-storage-unsupported"
/* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */
]: "This browser is not supported or 3rd party cookies and data may be disabled.",
[
"already-initialized"
/* AuthErrorCode.ALREADY_INITIALIZED */
]: "initializeAuth() has already been called with different options. To avoid this error, call initializeAuth() with the same options as when it was originally called, or call getAuth() to return the already initialized instance.",
[
"missing-recaptcha-token"
/* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */
]: "The reCAPTCHA token is missing when sending request to the backend.",
[
"invalid-recaptcha-token"
/* AuthErrorCode.INVALID_RECAPTCHA_TOKEN */
]: "The reCAPTCHA token is invalid when sending request to the backend.",
[
"invalid-recaptcha-action"
/* AuthErrorCode.INVALID_RECAPTCHA_ACTION */
]: "The reCAPTCHA action is invalid when sending request to the backend.",
[
"recaptcha-not-enabled"
/* AuthErrorCode.RECAPTCHA_NOT_ENABLED */
]: "reCAPTCHA Enterprise integration is not enabled for this project.",
[
"missing-client-type"
/* AuthErrorCode.MISSING_CLIENT_TYPE */
]: "The reCAPTCHA client type is missing when sending request to the backend.",
[
"missing-recaptcha-version"
/* AuthErrorCode.MISSING_RECAPTCHA_VERSION */
]: "The reCAPTCHA version is missing when sending request to the backend.",
[
"invalid-req-type"
/* AuthErrorCode.INVALID_REQ_TYPE */
]: "Invalid request parameters.",
[
"invalid-recaptcha-version"
/* AuthErrorCode.INVALID_RECAPTCHA_VERSION */
]: "The reCAPTCHA version is invalid when sending request to the backend.",
[
"unsupported-password-policy-schema-version"
/* AuthErrorCode.UNSUPPORTED_PASSWORD_POLICY_SCHEMA_VERSION */
]: "The password policy received from the backend uses a schema version that is not supported by this version of the Firebase SDK.",
[
"password-does-not-meet-requirements"
/* AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */
]: "The password does not meet the requirements.",
[
"invalid-hosting-link-domain"
/* AuthErrorCode.INVALID_HOSTING_LINK_DOMAIN */
]: "The provided Hosting link domain is not configured in Firebase Hosting or is not owned by the current project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`)."
};
}
function _prodErrorMap2() {
return {
[
"dependent-sdk-initialized-before-auth"
/* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
]: "Another Firebase SDK was initialized and is trying to use Auth before Auth is initialized. Please be sure to call `initializeAuth` or `getAuth` before starting any other Firebase SDK."
};
}
var debugErrorMap2 = _debugErrorMap2;
var prodErrorMap2 = _prodErrorMap2;
var _DEFAULT_AUTH_ERROR_FACTORY2 = new util.ErrorFactory("auth", "Firebase", _prodErrorMap2());
var AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY2 = {
ADMIN_ONLY_OPERATION: "auth/admin-restricted-operation",
ARGUMENT_ERROR: "auth/argument-error",
APP_NOT_AUTHORIZED: "auth/app-not-authorized",
APP_NOT_INSTALLED: "auth/app-not-installed",
CAPTCHA_CHECK_FAILED: "auth/captcha-check-failed",
CODE_EXPIRED: "auth/code-expired",
CORDOVA_NOT_READY: "auth/cordova-not-ready",
CORS_UNSUPPORTED: "auth/cors-unsupported",
CREDENTIAL_ALREADY_IN_USE: "auth/credential-already-in-use",
CREDENTIAL_MISMATCH: "auth/custom-token-mismatch",
CREDENTIAL_TOO_OLD_LOGIN_AGAIN: "auth/requires-recent-login",
DEPENDENT_SDK_INIT_BEFORE_AUTH: "auth/dependent-sdk-initialized-before-auth",
DYNAMIC_LINK_NOT_ACTIVATED: "auth/dynamic-link-not-activated",
EMAIL_CHANGE_NEEDS_VERIFICATION: "auth/email-change-needs-verification",
EMAIL_EXISTS: "auth/email-already-in-use",
EMULATOR_CONFIG_FAILED: "auth/emulator-config-failed",
EXPIRED_OOB_CODE: "auth/expired-action-code",
EXPIRED_POPUP_REQUEST: "auth/cancelled-popup-request",
INTERNAL_ERROR: "auth/internal-error",
INVALID_API_KEY: "auth/invalid-api-key",
INVALID_APP_CREDENTIAL: "auth/invalid-app-credential",
INVALID_APP_ID: "auth/invalid-app-id",
INVALID_AUTH: "auth/invalid-user-token",
INVALID_AUTH_EVENT: "auth/invalid-auth-event",
INVALID_CERT_HASH: "auth/invalid-cert-hash",
INVALID_CODE: "auth/invalid-verification-code",
INVALID_CONTINUE_URI: "auth/invalid-continue-uri",
INVALID_CORDOVA_CONFIGURATION: "auth/invalid-cordova-configuration",
INVALID_CUSTOM_TOKEN: "auth/invalid-custom-token",
INVALID_DYNAMIC_LINK_DOMAIN: "auth/invalid-dynamic-link-domain",
INVALID_EMAIL: "auth/invalid-email",
INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme",
INVALID_IDP_RESPONSE: "auth/invalid-credential",
INVALID_LOGIN_CREDENTIALS: "auth/invalid-credential",
INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload",
INVALID_MFA_SESSION: "auth/invalid-multi-factor-session",
INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id",
INVALID_OAUTH_PROVIDER: "auth/invalid-oauth-provider",
INVALID_OOB_CODE: "auth/invalid-action-code",
INVALID_ORIGIN: "auth/unauthorized-domain",
INVALID_PASSWORD: "auth/wrong-password",
INVALID_PERSISTENCE: "auth/invalid-persistence-type",
INVALID_PHONE_NUMBER: "auth/invalid-phone-number",
INVALID_PROVIDER_ID: "auth/invalid-provider-id",
INVALID_RECIPIENT_EMAIL: "auth/invalid-recipient-email",
INVALID_SENDER: "auth/invalid-sender",
INVALID_SESSION_INFO: "auth/invalid-verification-id",
INVALID_TENANT_ID: "auth/invalid-tenant-id",
MFA_INFO_NOT_FOUND: "auth/multi-factor-info-not-found",
MFA_REQUIRED: "auth/multi-factor-auth-required",
MISSING_ANDROID_PACKAGE_NAME: "auth/missing-android-pkg-name",
MISSING_APP_CREDENTIAL: "auth/missing-app-credential",
MISSING_AUTH_DOMAIN: "auth/auth-domain-config-required",
MISSING_CODE: "auth/missing-verification-code",
MISSING_CONTINUE_URI: "auth/missing-continue-uri",
MISSING_IFRAME_START: "auth/missing-iframe-start",
MISSING_IOS_BUNDLE_ID: "auth/missing-ios-bundle-id",
MISSING_OR_INVALID_NONCE: "auth/missing-or-invalid-nonce",
MISSING_MFA_INFO: "auth/missing-multi-factor-info",
MISSING_MFA_SESSION: "auth/missing-multi-factor-session",
MISSING_PHONE_NUMBER: "auth/missing-phone-number",
MISSING_PASSWORD: "auth/missing-password",
MISSING_SESSION_INFO: "auth/missing-verification-id",
MODULE_DESTROYED: "auth/app-deleted",
NEED_CONFIRMATION: "auth/account-exists-with-different-credential",
NETWORK_REQUEST_FAILED: "auth/network-request-failed",
NULL_USER: "auth/null-user",
NO_AUTH_EVENT: "auth/no-auth-event",
NO_SUCH_PROVIDER: "auth/no-such-provider",
OPERATION_NOT_ALLOWED: "auth/operation-not-allowed",
OPERATION_NOT_SUPPORTED: "auth/operation-not-supported-in-this-environment",
POPUP_BLOCKED: "auth/popup-blocked",
POPUP_CLOSED_BY_USER: "auth/popup-closed-by-user",
PROVIDER_ALREADY_LINKED: "auth/provider-already-linked",
QUOTA_EXCEEDED: "auth/quota-exceeded",
REDIRECT_CANCELLED_BY_USER: "auth/redirect-cancelled-by-user",
REDIRECT_OPERATION_PENDING: "auth/redirect-operation-pending",
REJECTED_CREDENTIAL: "auth/rejected-credential",
SECOND_FACTOR_ALREADY_ENROLLED: "auth/second-factor-already-in-use",
SECOND_FACTOR_LIMIT_EXCEEDED: "auth/maximum-second-factor-count-exceeded",
TENANT_ID_MISMATCH: "auth/tenant-id-mismatch",
TIMEOUT: "auth/timeout",
TOKEN_EXPIRED: "auth/user-token-expired",
TOO_MANY_ATTEMPTS_TRY_LATER: "auth/too-many-requests",
UNAUTHORIZED_DOMAIN: "auth/unauthorized-continue-uri",
UNSUPPORTED_FIRST_FACTOR: "auth/unsupported-first-factor",
UNSUPPORTED_PERSISTENCE: "auth/unsupported-persistence-type",
UNSUPPORTED_TENANT_OPERATION: "auth/unsupported-tenant-operation",
UNVERIFIED_EMAIL: "auth/unverified-email",
USER_CANCELLED: "auth/user-cancelled",
USER_DELETED: "auth/user-not-found",
USER_DISABLED: "auth/user-disabled",
USER_MISMATCH: "auth/user-mismatch",
USER_SIGNED_OUT: "auth/user-signed-out",
WEAK_PASSWORD: "auth/weak-password",
WEB_STORAGE_UNSUPPORTED: "auth/web-storage-unsupported",
ALREADY_INITIALIZED: "auth/already-initialized",
RECAPTCHA_NOT_ENABLED: "auth/recaptcha-not-enabled",
MISSING_RECAPTCHA_TOKEN: "auth/missing-recaptcha-token",
INVALID_RECAPTCHA_TOKEN: "auth/invalid-recaptcha-token",
INVALID_RECAPTCHA_ACTION: "auth/invalid-recaptcha-action",
MISSING_CLIENT_TYPE: "auth/missing-client-type",
MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version",
INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version",
INVALID_REQ_TYPE: "auth/invalid-req-type",
INVALID_HOSTING_LINK_DOMAIN: "auth/invalid-hosting-link-domain"
};
var logClient2 = new logger2.Logger("@firebase/auth");
function _logWarn2(msg, ...args) {
if (logClient2.logLevel <= logger2.LogLevel.WARN) {
logClient2.warn(`Auth (${app2.SDK_VERSION}): ${msg}`, ...args);
}
}
function _logError2(msg, ...args) {
if (logClient2.logLevel <= logger2.LogLevel.ERROR) {
logClient2.error(`Auth (${app2.SDK_VERSION}): ${msg}`, ...args);
}
}
function _fail2(authOrCode, ...rest) {
throw createErrorInternal2(authOrCode, ...rest);
}
function _createError2(authOrCode, ...rest) {
return createErrorInternal2(authOrCode, ...rest);
}
function _errorWithCustomMessage2(auth2, code, message) {
const errorMap = {
...prodErrorMap2(),
[code]: message
};
const factory2 = new util.ErrorFactory("auth", "Firebase", errorMap);
return factory2.create(code, {
appName: auth2.name
});
}
function _serverAppCurrentUserOperationNotSupportedError2(auth2) {
return _errorWithCustomMessage2(auth2, "operation-not-supported-in-this-environment", "Operations that alter the current user are not supported in conjunction with FirebaseServerApp");
}
function createErrorInternal2(authOrCode, ...rest) {
if (typeof authOrCode !== "string") {
const code = rest[0];
const fullParams = [...rest.slice(1)];
if (fullParams[0]) {
fullParams[0].appName = authOrCode.name;
}
return authOrCode._errorFactory.create(code, ...fullParams);
}
return _DEFAULT_AUTH_ERROR_FACTORY2.create(authOrCode, ...rest);
}
function _assert2(assertion, authOrCode, ...rest) {
if (!assertion) {
throw createErrorInternal2(authOrCode, ...rest);
}
}
function debugFail2(failure) {
const message = `INTERNAL ASSERTION FAILED: ` + failure;
_logError2(message);
throw new Error(message);
}
function debugAssert2(assertion, message) {
if (!assertion) {
debugFail2(message);
}
}
function _getCurrentUrl2() {
return typeof self !== "undefined" && self.location?.href || "";
}
function _isHttpOrHttps2() {
return _getCurrentScheme2() === "http:" || _getCurrentScheme2() === "https:";
}
function _getCurrentScheme2() {
return typeof self !== "undefined" && self.location?.protocol || null;
}
function _isOnline2() {
if (typeof navigator !== "undefined" && navigator && "onLine" in navigator && typeof navigator.onLine === "boolean" && // Apply only for traditional web apps and Chrome extensions.
// This is especially true for Cordova apps which have unreliable
// navigator.onLine behavior unless cordova-plugin-network-information is
// installed which overwrites the native navigator.onLine value and
// defines navigator.connection.
(_isHttpOrHttps2() || util.isBrowserExtension() || "connection" in navigator)) {
return navigator.onLine;
}
return true;
}
function _getUserLanguage2() {
if (typeof navigator === "undefined") {
return null;
}
const navigatorLanguage = navigator;
return (
// Most reliable, but only supported in Chrome/Firefox.
navigatorLanguage.languages && navigatorLanguage.languages[0] || // Supported in most browsers, but returns the language of the browser
// UI, not the language set in browser settings.
navigatorLanguage.language || // Couldn't determine language.
null
);
}
var Delay2 = class {
constructor(shortDelay, longDelay) {
this.shortDelay = shortDelay;
this.longDelay = longDelay;
debugAssert2(longDelay > shortDelay, "Short delay should be less than long delay!");
this.isMobile = util.isMobileCordova() || util.isReactNative();
}
get() {
if (!_isOnline2()) {
return Math.min(5e3, this.shortDelay);
}
return this.isMobile ? this.longDelay : this.shortDelay;
}
};
function _emulatorUrl2(config, path) {
debugAssert2(config.emulator, "Emulator should always be set here");
const { url } = config.emulator;
if (!path) {
return url;
}
return `${url}${path.startsWith("/") ? path.slice(1) : path}`;
}
var FetchProvider2 = class {
static initialize(fetchImpl, headersImpl, responseImpl) {
this.fetchImpl = fetchImpl;
if (headersImpl) {
this.headersImpl = headersImpl;
}
if (responseImpl) {
this.responseImpl = responseImpl;
}
}
static fetch() {
if (this.fetchImpl) {
return this.fetchImpl;
}
if (typeof self !== "undefined" && "fetch" in self) {
return self.fetch;
}
if (typeof globalThis !== "undefined" && globalThis.fetch) {
return globalThis.fetch;
}
if (typeof fetch !== "undefined") {
return fetch;
}
debugFail2("Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill");
}
static headers() {
if (this.headersImpl) {
return this.headersImpl;
}
if (typeof self !== "undefined" && "Headers" in self) {
return self.Headers;
}
if (typeof globalThis !== "undefined" && globalThis.Headers) {
return globalThis.Headers;
}
if (typeof Headers !== "undefined") {
return Headers;
}
debugFail2("Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill");
}
static response() {
if (this.responseImpl) {
return this.responseImpl;
}
if (typeof self !== "undefined" && "Response" in self) {
return self.Response;
}
if (typeof globalThis !== "undefined" && globalThis.Response) {
return globalThis.Response;
}
if (typeof Response !== "undefined") {
return Response;
}
debugFail2("Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill");
}
};
var SERVER_ERROR_MAP2 = {
// Custom token errors.
[
"CREDENTIAL_MISMATCH"
/* ServerError.CREDENTIAL_MISMATCH */
]: "custom-token-mismatch",
// This can only happen if the SDK sends a bad request.
[
"MISSING_CUSTOM_TOKEN"
/* ServerError.MISSING_CUSTOM_TOKEN */
]: "internal-error",
// Create Auth URI errors.
[
"INVALID_IDENTIFIER"
/* ServerError.INVALID_IDENTIFIER */
]: "invalid-email",
// This can only happen if the SDK sends a bad request.
[
"MISSING_CONTINUE_URI"
/* ServerError.MISSING_CONTINUE_URI */
]: "internal-error",
// Sign in with email and password errors (some apply to sign up too).
[
"INVALID_PASSWORD"
/* ServerError.INVALID_PASSWORD */
]: "wrong-password",
// This can only happen if the SDK sends a bad request.
[
"MISSING_PASSWORD"
/* ServerError.MISSING_PASSWORD */
]: "missing-password",
// Thrown if Email Enumeration Protection is enabled in the project and the email or password is
// invalid.
[
"INVALID_LOGIN_CREDENTIALS"
/* ServerError.INVALID_LOGIN_CREDENTIALS */
]: "invalid-credential",
// Sign up with email and password errors.
[
"EMAIL_EXISTS"
/* ServerError.EMAIL_EXISTS */
]: "email-already-in-use",
[
"PASSWORD_LOGIN_DISABLED"
/* ServerError.PASSWORD_LOGIN_DISABLED */
]: "operation-not-allowed",
// Verify assertion for sign in with credential errors:
[
"INVALID_IDP_RESPONSE"
/* ServerError.INVALID_IDP_RESPONSE */
]: "invalid-credential",
[
"INVALID_PENDING_TOKEN"
/* ServerError.INVALID_PENDING_TOKEN */
]: "invalid-credential",
[
"FEDERATED_USER_ID_ALREADY_LINKED"
/* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */
]: "credential-already-in-use",
// This can only happen if the SDK sends a bad request.
[
"MISSING_REQ_TYPE"
/* ServerError.MISSING_REQ_TYPE */
]: "internal-error",
// Send Password reset email errors:
[
"EMAIL_NOT_FOUND"
/* ServerError.EMAIL_NOT_FOUND */
]: "user-not-found",
[
"RESET_PASSWORD_EXCEED_LIMIT"
/* ServerError.RESET_PASSWORD_EXCEED_LIMIT */
]: "too-many-requests",
[
"EXPIRED_OOB_CODE"
/* ServerError.EXPIRED_OOB_CODE */
]: "expired-action-code",
[
"INVALID_OOB_CODE"
/* ServerError.INVALID_OOB_CODE */
]: "invalid-action-code",
// This can only happen if the SDK sends a bad request.
[
"MISSING_OOB_CODE"
/* ServerError.MISSING_OOB_CODE */
]: "internal-error",
// Operations that require ID token in request:
[
"CREDENTIAL_TOO_OLD_LOGIN_AGAIN"
/* ServerError.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */
]: "requires-recent-login",
[
"INVALID_ID_TOKEN"
/* ServerError.INVALID_ID_TOKEN */
]: "invalid-user-token",
[
"TOKEN_EXPIRED"
/* ServerError.TOKEN_EXPIRED */
]: "user-token-expired",
[
"USER_NOT_FOUND"
/* ServerError.USER_NOT_FOUND */
]: "user-token-expired",
// Other errors.
[
"TOO_MANY_ATTEMPTS_TRY_LATER"
/* ServerError.TOO_MANY_ATTEMPTS_TRY_LATER */
]: "too-many-requests",
[
"PASSWORD_DOES_NOT_MEET_REQUIREMENTS"
/* ServerError.PASSWORD_DOES_NOT_MEET_REQUIREMENTS */
]: "password-does-not-meet-requirements",
// Phone Auth related errors.
[
"INVALID_CODE"
/* ServerError.INVALID_CODE */
]: "invalid-verification-code",
[
"INVALID_SESSION_INFO"
/* ServerError.INVALID_SESSION_INFO */
]: "invalid-verification-id",
[
"INVALID_TEMPORARY_PROOF"
/* ServerError.INVALID_TEMPORARY_PROOF */
]: "invalid-credential",
[
"MISSING_SESSION_INFO"
/* ServerError.MISSING_SESSION_INFO */
]: "missing-verification-id",
[
"SESSION_EXPIRED"
/* ServerError.SESSION_EXPIRED */
]: "code-expired",
// Other action code errors when additional settings passed.
// MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above.
// This is OK as this error will be caught by client side validation.
[
"MISSING_ANDROID_PACKAGE_NAME"
/* ServerError.MISSING_ANDROID_PACKAGE_NAME */
]: "missing-android-pkg-name",
[
"UNAUTHORIZED_DOMAIN"
/* ServerError.UNAUTHORIZED_DOMAIN */
]: "unauthorized-continue-uri",
// getProjectConfig errors when clientId is passed.
[
"INVALID_OAUTH_CLIENT_ID"
/* ServerError.INVALID_OAUTH_CLIENT_ID */
]: "invalid-oauth-client-id",
// User actions (sign-up or deletion) disabled errors.
[
"ADMIN_ONLY_OPERATION"
/* ServerError.ADMIN_ONLY_OPERATION */
]: "admin-restricted-operation",
// Multi factor related errors.
[
"INVALID_MFA_PENDING_CREDENTIAL"
/* ServerError.INVALID_MFA_PENDING_CREDENTIAL */
]: "invalid-multi-factor-session",
[
"MFA_ENROLLMENT_NOT_FOUND"
/* ServerError.MFA_ENROLLMENT_NOT_FOUND */
]: "multi-factor-info-not-found",
[
"MISSING_MFA_ENROLLMENT_ID"
/* ServerError.MISSING_MFA_ENROLLMENT_ID */
]: "missing-multi-factor-info",
[
"MISSING_MFA_PENDING_CREDENTIAL"
/* ServerError.MISSING_MFA_PENDING_CREDENTIAL */
]: "missing-multi-factor-session",
[
"SECOND_FACTOR_EXISTS"
/* ServerError.SECOND_FACTOR_EXISTS */
]: "second-factor-already-in-use",
[
"SECOND_FACTOR_LIMIT_EXCEEDED"
/* ServerError.SECOND_FACTOR_LIMIT_EXCEEDED */
]: "maximum-second-factor-count-exceeded",
// Blocking functions related errors.
[
"BLOCKING_FUNCTION_ERROR_RESPONSE"
/* ServerError.BLOCKING_FUNCTION_ERROR_RESPONSE */
]: "internal-error",
// Recaptcha related errors.
[
"RECAPTCHA_NOT_ENABLED"
/* ServerError.RECAPTCHA_NOT_ENABLED */
]: "recaptcha-not-enabled",
[
"MISSING_RECAPTCHA_TOKEN"
/* ServerError.MISSING_RECAPTCHA_TOKEN */
]: "missing-recaptcha-token",
[
"INVALID_RECAPTCHA_TOKEN"
/* ServerError.INVALID_RECAPTCHA_TOKEN */
]: "invalid-recaptcha-token",
[
"INVALID_RECAPTCHA_ACTION"
/* ServerError.INVALID_RECAPTCHA_ACTION */
]: "invalid-recaptcha-action",
[
"MISSING_CLIENT_TYPE"
/* ServerError.MISSING_CLIENT_TYPE */
]: "missing-client-type",
[
"MISSING_RECAPTCHA_VERSION"
/* ServerError.MISSING_RECAPTCHA_VERSION */
]: "missing-recaptcha-version",
[
"INVALID_RECAPTCHA_VERSION"
/* ServerError.INVALID_RECAPTCHA_VERSION */
]: "invalid-recaptcha-version",
[
"INVALID_REQ_TYPE"
/* ServerError.INVALID_REQ_TYPE */
]: "invalid-req-type"
/* AuthErrorCode.INVALID_REQ_TYPE */
};
var CookieAuthProxiedEndpoints2 = [
"/v1/accounts:signInWithCustomToken",
"/v1/accounts:signInWithEmailLink",
"/v1/accounts:signInWithIdp",
"/v1/accounts:signInWithPassword",
"/v1/accounts:signInWithPhoneNumber",
"/v1/token"
/* Endpoint.TOKEN */
];
var DEFAULT_API_TIMEOUT_MS2 = new Delay2(3e4, 6e4);
function _addTidIfNecessary2(auth2, request) {
if (auth2.tenantId && !request.tenantId) {
return {
...request,
tenantId: auth2.tenantId
};
}
return request;
}
async function _performApiRequest2(auth2, method, path, request, customErrorMap = {}) {
return _performFetchWithErrorHandling2(auth2, customErrorMap, async () => {
let body = {};
let params = {};
if (request) {
if (method === "GET") {
params = request;
} else {
body = {
body: JSON.stringify(request)
};
}
}
const query = util.querystring({
key: auth2.config.apiKey,
...params
}).slice(1);
const headers = await auth2._getAdditionalHeaders();
headers[
"Content-Type"
/* HttpHeader.CONTENT_TYPE */
] = "application/json";
if (auth2.languageCode) {
headers[
"X-Firebase-Locale"
/* HttpHeader.X_FIREBASE_LOCALE */
] = auth2.languageCode;
}
const fetchArgs = {
method,
headers,
...body
};
if (!util.isCloudflareWorker()) {
fetchArgs.referrerPolicy = "no-referrer";
}
if (auth2.emulatorConfig && util.isCloudWorkstation(auth2.emulatorConfig.host)) {
fetchArgs.credentials = "include";
}
return FetchProvider2.fetch()(await _getFinalTarget2(auth2, auth2.config.apiHost, path, query), fetchArgs);
});
}
async function _performFetchWithErrorHandling2(auth2, customErrorMap, fetchFn) {
auth2._canInitEmulator = false;
const errorMap = { ...SERVER_ERROR_MAP2, ...customErrorMap };
try {
const networkTimeout = new NetworkTimeout2(auth2);
const response = await Promise.race([
fetchFn(),
networkTimeout.promise
]);
networkTimeout.clearNetworkTimeout();
const json = await response.json();
if ("needConfirmation" in json) {
throw _makeTaggedError2(auth2, "account-exists-with-different-credential", json);
}
if (response.ok && !("errorMessage" in json)) {
return json;
} else {
const errorMessage = response.ok ? json.errorMessage : json.error.message;
const [serverErrorCode, serverErrorMessage] = errorMessage.split(" : ");
if (serverErrorCode === "FEDERATED_USER_ID_ALREADY_LINKED") {
throw _makeTaggedError2(auth2, "credential-already-in-use", json);
} else if (serverErrorCode === "EMAIL_EXISTS") {
throw _makeTaggedError2(auth2, "email-already-in-use", json);
} else if (serverErrorCode === "USER_DISABLED") {
throw _makeTaggedError2(auth2, "user-disabled", json);
}
const authError = errorMap[serverErrorCode] || serverErrorCode.toLowerCase().replace(/[_\s]+/g, "-");
if (serverErrorMessage) {
throw _errorWithCustomMessage2(auth2, authError, serverErrorMessage);
} else {
_fail2(auth2, authError);
}
}
} catch (e) {
if (e instanceof util.FirebaseError) {
throw e;
}
_fail2(auth2, "network-request-failed", { "message": String(e) });
}
}
async function _performSignInRequest2(auth2, method, path, request, customErrorMap = {}) {
const serverResponse = await _performApiRequest2(auth2, method, path, request, customErrorMap);
if ("mfaPendingCredential" in serverResponse) {
_fail2(auth2, "multi-factor-auth-required", {
_serverResponse: serverResponse
});
}
return serverResponse;
}
async function _getFinalTarget2(auth2, host, path, query) {
const base = `${host}${path}?${query}`;
const authInternal = auth2;
const finalTarget = authInternal.config.emulator ? _emulatorUrl2(auth2.config, base) : `${auth2.config.apiScheme}://${base}`;
if (CookieAuthProxiedEndpoints2.includes(path)) {
await authInternal._persistenceManagerAvailable;
if (authInternal._getPersistenceType() === "COOKIE") {
const cookiePersistence = authInternal._getPersistence();
return cookiePersistence._getFinalTarget(finalTarget).toString();
}
}
return finalTarget;
}
function _parseEnforcementState2(enforcementStateStr) {
switch (enforcementStateStr) {
case "ENFORCE":
return "ENFORCE";
case "AUDIT":
return "AUDIT";
case "OFF":
return "OFF";
default:
return "ENFORCEMENT_STATE_UNSPECIFIED";
}
}
var NetworkTimeout2 = class {
clearNetworkTimeout() {
clearTimeout(this.timer);
}
constructor(auth2) {
this.auth = auth2;
this.timer = null;
this.promise = new Promise((_, reject) => {
this.timer = setTimeout(() => {
return reject(_createError2(
this.auth,
"network-request-failed"
/* AuthErrorCode.NETWORK_REQUEST_FAILED */
));
}, DEFAULT_API_TIMEOUT_MS2.get());
});
}
};
function _makeTaggedError2(auth2, code, response) {
const errorParams = {
appName: auth2.name
};
if (response.email) {
errorParams.email = response.email;
}
if (response.phoneNumber) {
errorParams.phoneNumber = response.phoneNumber;
}
const error = _createError2(auth2, code, errorParams);
error.customData._tokenResponse = response;
return error;
}
function isEnterprise2(grecaptcha) {
return grecaptcha !== void 0 && grecaptcha.enterprise !== void 0;
}
var RecaptchaConfig2 = class {
constructor(response) {
this.siteKey = "";
this.recaptchaEnforcementState = [];
if (response.recaptchaKey === void 0) {
throw new Error("recaptchaKey undefined");
}
this.siteKey = response.recaptchaKey.split("/")[3];
this.recaptchaEnforcementState = response.recaptchaEnforcementState;
}
/**
* Returns the reCAPTCHA Enterprise enforcement state for the given provider.
*
* @param providerStr - The provider whose enforcement state is to be returned.
* @returns The reCAPTCHA Enterprise enforcement state for the given provider.
*/
getProviderEnforcementState(providerStr) {
if (!this.recaptchaEnforcementState || this.recaptchaEnforcementState.length === 0) {
return null;
}
for (const recaptchaEnforcementState of this.recaptchaEnforcementState) {
if (recaptchaEnforcementState.provider && recaptchaEnforcementState.provider === providerStr) {
return _parseEnforcementState2(recaptchaEnforcementState.enforcementState);
}
}
return null;
}
/**
* Returns true if the reCAPTCHA Enterprise enforcement state for the provider is set to ENFORCE or AUDIT.
*
* @param providerStr - The provider whose enablement state is to be returned.
* @returns Whether or not reCAPTCHA Enterprise protection is enabled for the given provider.
*/
isProviderEnabled(providerStr) {
return this.getProviderEnforcementState(providerStr) === "ENFORCE" || this.getProviderEnforcementState(providerStr) === "AUDIT";
}
/**
* Returns true if reCAPTCHA Enterprise protection is enabled in at least one provider, otherwise
* returns false.
*
* @returns Whether or not reCAPTCHA Enterprise protection is enabled for at least one provider.
*/
isAnyProviderEnabled() {
return this.isProviderEnabled(
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
) || this.isProviderEnabled(
"PHONE_PROVIDER"
/* RecaptchaAuthProvider.PHONE_PROVIDER */
);
}
};
async function getRecaptchaConfig2(auth2, request) {
return _performApiRequest2(auth2, "GET", "/v2/recaptchaConfig", _addTidIfNecessary2(auth2, request));
}
async function deleteAccount2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:delete", request);
}
async function deleteLinkedAccounts2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:update", request);
}
async function getAccountInfo2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:lookup", request);
}
function utcTimestampToDateString2(utcTimestamp) {
if (!utcTimestamp) {
return void 0;
}
try {
const date = new Date(Number(utcTimestamp));
if (!isNaN(date.getTime())) {
return date.toUTCString();
}
} catch (e) {
}
return void 0;
}
function getIdToken2(user, forceRefresh = false) {
return util.getModularInstance(user).getIdToken(forceRefresh);
}
async function getIdTokenResult2(user, forceRefresh = false) {
const userInternal = util.getModularInstance(user);
const token = await userInternal.getIdToken(forceRefresh);
const claims = _parseToken2(token);
_assert2(
claims && claims.exp && claims.auth_time && claims.iat,
userInternal.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const firebase = typeof claims.firebase === "object" ? claims.firebase : void 0;
const signInProvider = firebase?.["sign_in_provider"];
return {
claims,
token,
authTime: utcTimestampToDateString2(secondsStringToMilliseconds2(claims.auth_time)),
issuedAtTime: utcTimestampToDateString2(secondsStringToMilliseconds2(claims.iat)),
expirationTime: utcTimestampToDateString2(secondsStringToMilliseconds2(claims.exp)),
signInProvider: signInProvider || null,
signInSecondFactor: firebase?.["sign_in_second_factor"] || null
};
}
function secondsStringToMilliseconds2(seconds) {
return Number(seconds) * 1e3;
}
function _parseToken2(token) {
const [algorithm, payload, signature] = token.split(".");
if (algorithm === void 0 || payload === void 0 || signature === void 0) {
_logError2("JWT malformed, contained fewer than 3 sections");
return null;
}
try {
const decoded = util.base64Decode(payload);
if (!decoded) {
_logError2("Failed to decode base64 JWT payload");
return null;
}
return JSON.parse(decoded);
} catch (e) {
_logError2("Caught error parsing JWT payload as JSON", e?.toString());
return null;
}
}
function _tokenExpiresIn2(token) {
const parsedToken = _parseToken2(token);
_assert2(
parsedToken,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert2(
typeof parsedToken.exp !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert2(
typeof parsedToken.iat !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return Number(parsedToken.exp) - Number(parsedToken.iat);
}
async function _logoutIfInvalidated2(user, promise, bypassAuthState = false) {
if (bypassAuthState) {
return promise;
}
try {
return await promise;
} catch (e) {
if (e instanceof util.FirebaseError && isUserInvalidated2(e)) {
if (user.auth.currentUser === user) {
await user.auth.signOut();
}
}
throw e;
}
}
function isUserInvalidated2({ code }) {
return code === `auth/${"user-disabled"}` || code === `auth/${"user-token-expired"}`;
}
var ProactiveRefresh2 = class {
constructor(user) {
this.user = user;
this.isRunning = false;
this.timerId = null;
this.errorBackoff = 3e4;
}
_start() {
if (this.isRunning) {
return;
}
this.isRunning = true;
this.schedule();
}
_stop() {
if (!this.isRunning) {
return;
}
this.isRunning = false;
if (this.timerId !== null) {
clearTimeout(this.timerId);
}
}
getInterval(wasError) {
if (wasError) {
const interval = this.errorBackoff;
this.errorBackoff = Math.min(
this.errorBackoff * 2,
96e4
/* Duration.RETRY_BACKOFF_MAX */
);
return interval;
} else {
this.errorBackoff = 3e4;
const expTime = this.user.stsTokenManager.expirationTime ?? 0;
const interval = expTime - Date.now() - 3e5;
return Math.max(0, interval);
}
}
schedule(wasError = false) {
if (!this.isRunning) {
return;
}
const interval = this.getInterval(wasError);
this.timerId = setTimeout(async () => {
await this.iteration();
}, interval);
}
async iteration() {
try {
await this.user.getIdToken(true);
} catch (e) {
if (e?.code === `auth/${"network-request-failed"}`) {
this.schedule(
/* wasError */
true
);
}
return;
}
this.schedule();
}
};
var UserMetadata2 = class {
constructor(createdAt, lastLoginAt) {
this.createdAt = createdAt;
this.lastLoginAt = lastLoginAt;
this._initializeTime();
}
_initializeTime() {
this.lastSignInTime = utcTimestampToDateString2(this.lastLoginAt);
this.creationTime = utcTimestampToDateString2(this.createdAt);
}
_copy(metadata) {
this.createdAt = metadata.createdAt;
this.lastLoginAt = metadata.lastLoginAt;
this._initializeTime();
}
toJSON() {
return {
createdAt: this.createdAt,
lastLoginAt: this.lastLoginAt
};
}
};
async function _reloadWithoutSaving2(user) {
const auth2 = user.auth;
const idToken = await user.getIdToken();
const response = await _logoutIfInvalidated2(user, getAccountInfo2(auth2, { idToken }));
_assert2(
response?.users.length,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const coreAccount = response.users[0];
user._notifyReloadListener(coreAccount);
const newProviderData = coreAccount.providerUserInfo?.length ? extractProviderData2(coreAccount.providerUserInfo) : [];
const providerData = mergeProviderData2(user.providerData, newProviderData);
const oldIsAnonymous = user.isAnonymous;
const newIsAnonymous = !(user.email && coreAccount.passwordHash) && !providerData?.length;
const isAnonymous = !oldIsAnonymous ? false : newIsAnonymous;
const updates = {
uid: coreAccount.localId,
displayName: coreAccount.displayName || null,
photoURL: coreAccount.photoUrl || null,
email: coreAccount.email || null,
emailVerified: coreAccount.emailVerified || false,
phoneNumber: coreAccount.phoneNumber || null,
tenantId: coreAccount.tenantId || null,
providerData,
metadata: new UserMetadata2(coreAccount.createdAt, coreAccount.lastLoginAt),
isAnonymous
};
Object.assign(user, updates);
}
async function reload2(user) {
const userInternal = util.getModularInstance(user);
await _reloadWithoutSaving2(userInternal);
await userInternal.auth._persistUserIfCurrent(userInternal);
userInternal.auth._notifyListenersIfCurrent(userInternal);
}
function mergeProviderData2(original, newData) {
const deduped = original.filter((o) => !newData.some((n) => n.providerId === o.providerId));
return [...deduped, ...newData];
}
function extractProviderData2(providers) {
return providers.map(({ providerId, ...provider }) => {
return {
providerId,
uid: provider.rawId || "",
displayName: provider.displayName || null,
email: provider.email || null,
phoneNumber: provider.phoneNumber || null,
photoURL: provider.photoUrl || null
};
});
}
async function requestStsToken2(auth2, refreshToken) {
const response = await _performFetchWithErrorHandling2(auth2, {}, async () => {
const body = util.querystring({
"grant_type": "refresh_token",
"refresh_token": refreshToken
}).slice(1);
const { tokenApiHost, apiKey } = auth2.config;
const url = await _getFinalTarget2(auth2, tokenApiHost, "/v1/token", `key=${apiKey}`);
const headers = await auth2._getAdditionalHeaders();
headers[
"Content-Type"
/* HttpHeader.CONTENT_TYPE */
] = "application/x-www-form-urlencoded";
const options = {
method: "POST",
headers,
body
};
if (auth2.emulatorConfig && util.isCloudWorkstation(auth2.emulatorConfig.host)) {
options.credentials = "include";
}
return FetchProvider2.fetch()(url, options);
});
return {
accessToken: response.access_token,
expiresIn: response.expires_in,
refreshToken: response.refresh_token
};
}
async function revokeToken2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v2/accounts:revokeToken", _addTidIfNecessary2(auth2, request));
}
var StsTokenManager2 = class _StsTokenManager {
constructor() {
this.refreshToken = null;
this.accessToken = null;
this.expirationTime = null;
}
get isExpired() {
return !this.expirationTime || Date.now() > this.expirationTime - 3e4;
}
updateFromServerResponse(response) {
_assert2(
response.idToken,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert2(
typeof response.idToken !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert2(
typeof response.refreshToken !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const expiresIn = "expiresIn" in response && typeof response.expiresIn !== "undefined" ? Number(response.expiresIn) : _tokenExpiresIn2(response.idToken);
this.updateTokensAndExpiration(response.idToken, response.refreshToken, expiresIn);
}
updateFromIdToken(idToken) {
_assert2(
idToken.length !== 0,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const expiresIn = _tokenExpiresIn2(idToken);
this.updateTokensAndExpiration(idToken, null, expiresIn);
}
async getToken(auth2, forceRefresh = false) {
if (!forceRefresh && this.accessToken && !this.isExpired) {
return this.accessToken;
}
_assert2(
this.refreshToken,
auth2,
"user-token-expired"
/* AuthErrorCode.TOKEN_EXPIRED */
);
if (this.refreshToken) {
await this.refresh(auth2, this.refreshToken);
return this.accessToken;
}
return null;
}
clearRefreshToken() {
this.refreshToken = null;
}
async refresh(auth2, oldToken) {
const { accessToken, refreshToken, expiresIn } = await requestStsToken2(auth2, oldToken);
this.updateTokensAndExpiration(accessToken, refreshToken, Number(expiresIn));
}
updateTokensAndExpiration(accessToken, refreshToken, expiresInSec) {
this.refreshToken = refreshToken || null;
this.accessToken = accessToken || null;
this.expirationTime = Date.now() + expiresInSec * 1e3;
}
static fromJSON(appName, object) {
const { refreshToken, accessToken, expirationTime } = object;
const manager = new _StsTokenManager();
if (refreshToken) {
_assert2(typeof refreshToken === "string", "internal-error", {
appName
});
manager.refreshToken = refreshToken;
}
if (accessToken) {
_assert2(typeof accessToken === "string", "internal-error", {
appName
});
manager.accessToken = accessToken;
}
if (expirationTime) {
_assert2(typeof expirationTime === "number", "internal-error", {
appName
});
manager.expirationTime = expirationTime;
}
return manager;
}
toJSON() {
return {
refreshToken: this.refreshToken,
accessToken: this.accessToken,
expirationTime: this.expirationTime
};
}
_assign(stsTokenManager) {
this.accessToken = stsTokenManager.accessToken;
this.refreshToken = stsTokenManager.refreshToken;
this.expirationTime = stsTokenManager.expirationTime;
}
_clone() {
return Object.assign(new _StsTokenManager(), this.toJSON());
}
_performRefresh() {
return debugFail2("not implemented");
}
};
function assertStringOrUndefined2(assertion, appName) {
_assert2(typeof assertion === "string" || typeof assertion === "undefined", "internal-error", { appName });
}
var UserImpl2 = class _UserImpl {
constructor({ uid, auth: auth2, stsTokenManager, ...opt }) {
this.providerId = "firebase";
this.proactiveRefresh = new ProactiveRefresh2(this);
this.reloadUserInfo = null;
this.reloadListener = null;
this.uid = uid;
this.auth = auth2;
this.stsTokenManager = stsTokenManager;
this.accessToken = stsTokenManager.accessToken;
this.displayName = opt.displayName || null;
this.email = opt.email || null;
this.emailVerified = opt.emailVerified || false;
this.phoneNumber = opt.phoneNumber || null;
this.photoURL = opt.photoURL || null;
this.isAnonymous = opt.isAnonymous || false;
this.tenantId = opt.tenantId || null;
this.providerData = opt.providerData ? [...opt.providerData] : [];
this.metadata = new UserMetadata2(opt.createdAt || void 0, opt.lastLoginAt || void 0);
}
async getIdToken(forceRefresh) {
const accessToken = await _logoutIfInvalidated2(this, this.stsTokenManager.getToken(this.auth, forceRefresh));
_assert2(
accessToken,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
if (this.accessToken !== accessToken) {
this.accessToken = accessToken;
await this.auth._persistUserIfCurrent(this);
this.auth._notifyListenersIfCurrent(this);
}
return accessToken;
}
getIdTokenResult(forceRefresh) {
return getIdTokenResult2(this, forceRefresh);
}
reload() {
return reload2(this);
}
_assign(user) {
if (this === user) {
return;
}
_assert2(
this.uid === user.uid,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
this.displayName = user.displayName;
this.photoURL = user.photoURL;
this.email = user.email;
this.emailVerified = user.emailVerified;
this.phoneNumber = user.phoneNumber;
this.isAnonymous = user.isAnonymous;
this.tenantId = user.tenantId;
this.providerData = user.providerData.map((userInfo) => ({ ...userInfo }));
this.metadata._copy(user.metadata);
this.stsTokenManager._assign(user.stsTokenManager);
}
_clone(auth2) {
const newUser = new _UserImpl({
...this,
auth: auth2,
stsTokenManager: this.stsTokenManager._clone()
});
newUser.metadata._copy(this.metadata);
return newUser;
}
_onReload(callback) {
_assert2(
!this.reloadListener,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
this.reloadListener = callback;
if (this.reloadUserInfo) {
this._notifyReloadListener(this.reloadUserInfo);
this.reloadUserInfo = null;
}
}
_notifyReloadListener(userInfo) {
if (this.reloadListener) {
this.reloadListener(userInfo);
} else {
this.reloadUserInfo = userInfo;
}
}
_startProactiveRefresh() {
this.proactiveRefresh._start();
}
_stopProactiveRefresh() {
this.proactiveRefresh._stop();
}
async _updateTokensIfNecessary(response, reload3 = false) {
let tokensRefreshed = false;
if (response.idToken && response.idToken !== this.stsTokenManager.accessToken) {
this.stsTokenManager.updateFromServerResponse(response);
tokensRefreshed = true;
}
if (reload3) {
await _reloadWithoutSaving2(this);
}
await this.auth._persistUserIfCurrent(this);
if (tokensRefreshed) {
this.auth._notifyListenersIfCurrent(this);
}
}
async delete() {
if (app2._isFirebaseServerApp(this.auth.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(this.auth));
}
const idToken = await this.getIdToken();
await _logoutIfInvalidated2(this, deleteAccount2(this.auth, { idToken }));
this.stsTokenManager.clearRefreshToken();
return this.auth.signOut();
}
toJSON() {
return {
uid: this.uid,
email: this.email || void 0,
emailVerified: this.emailVerified,
displayName: this.displayName || void 0,
isAnonymous: this.isAnonymous,
photoURL: this.photoURL || void 0,
phoneNumber: this.phoneNumber || void 0,
tenantId: this.tenantId || void 0,
providerData: this.providerData.map((userInfo) => ({ ...userInfo })),
stsTokenManager: this.stsTokenManager.toJSON(),
// Redirect event ID must be maintained in case there is a pending
// redirect event.
_redirectEventId: this._redirectEventId,
...this.metadata.toJSON(),
// Required for compatibility with the legacy SDK (go/firebase-auth-sdk-persistence-parsing):
apiKey: this.auth.config.apiKey,
appName: this.auth.name
// Missing authDomain will be tolerated by the legacy SDK.
// stsTokenManager.apiKey isn't actually required (despite the legacy SDK persisting it).
};
}
get refreshToken() {
return this.stsTokenManager.refreshToken || "";
}
static _fromJSON(auth2, object) {
const displayName = object.displayName ?? void 0;
const email = object.email ?? void 0;
const phoneNumber = object.phoneNumber ?? void 0;
const photoURL = object.photoURL ?? void 0;
const tenantId = object.tenantId ?? void 0;
const _redirectEventId = object._redirectEventId ?? void 0;
const createdAt = object.createdAt ?? void 0;
const lastLoginAt = object.lastLoginAt ?? void 0;
const { uid, emailVerified, isAnonymous, providerData, stsTokenManager: plainObjectTokenManager } = object;
_assert2(
uid && plainObjectTokenManager,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const stsTokenManager = StsTokenManager2.fromJSON(this.name, plainObjectTokenManager);
_assert2(
typeof uid === "string",
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
assertStringOrUndefined2(displayName, auth2.name);
assertStringOrUndefined2(email, auth2.name);
_assert2(
typeof emailVerified === "boolean",
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
_assert2(
typeof isAnonymous === "boolean",
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
assertStringOrUndefined2(phoneNumber, auth2.name);
assertStringOrUndefined2(photoURL, auth2.name);
assertStringOrUndefined2(tenantId, auth2.name);
assertStringOrUndefined2(_redirectEventId, auth2.name);
assertStringOrUndefined2(createdAt, auth2.name);
assertStringOrUndefined2(lastLoginAt, auth2.name);
const user = new _UserImpl({
uid,
auth: auth2,
email,
emailVerified,
displayName,
isAnonymous,
photoURL,
phoneNumber,
tenantId,
stsTokenManager,
createdAt,
lastLoginAt
});
if (providerData && Array.isArray(providerData)) {
user.providerData = providerData.map((userInfo) => ({ ...userInfo }));
}
if (_redirectEventId) {
user._redirectEventId = _redirectEventId;
}
return user;
}
/**
* Initialize a User from an idToken server response
* @param auth
* @param idTokenResponse
*/
static async _fromIdTokenResponse(auth2, idTokenResponse, isAnonymous = false) {
const stsTokenManager = new StsTokenManager2();
stsTokenManager.updateFromServerResponse(idTokenResponse);
const user = new _UserImpl({
uid: idTokenResponse.localId,
auth: auth2,
stsTokenManager,
isAnonymous
});
await _reloadWithoutSaving2(user);
return user;
}
/**
* Initialize a User from an idToken server response
* @param auth
* @param idTokenResponse
*/
static async _fromGetAccountInfoResponse(auth2, response, idToken) {
const coreAccount = response.users[0];
_assert2(
coreAccount.localId !== void 0,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const providerData = coreAccount.providerUserInfo !== void 0 ? extractProviderData2(coreAccount.providerUserInfo) : [];
const isAnonymous = !(coreAccount.email && coreAccount.passwordHash) && !providerData?.length;
const stsTokenManager = new StsTokenManager2();
stsTokenManager.updateFromIdToken(idToken);
const user = new _UserImpl({
uid: coreAccount.localId,
auth: auth2,
stsTokenManager,
isAnonymous
});
const updates = {
uid: coreAccount.localId,
displayName: coreAccount.displayName || null,
photoURL: coreAccount.photoUrl || null,
email: coreAccount.email || null,
emailVerified: coreAccount.emailVerified || false,
phoneNumber: coreAccount.phoneNumber || null,
tenantId: coreAccount.tenantId || null,
providerData,
metadata: new UserMetadata2(coreAccount.createdAt, coreAccount.lastLoginAt),
isAnonymous: !(coreAccount.email && coreAccount.passwordHash) && !providerData?.length
};
Object.assign(user, updates);
return user;
}
};
var instanceCache2 = /* @__PURE__ */ new Map();
function _getInstance2(cls) {
debugAssert2(cls instanceof Function, "Expected a class definition");
let instance = instanceCache2.get(cls);
if (instance) {
debugAssert2(instance instanceof cls, "Instance stored in cache mismatched with class");
return instance;
}
instance = new cls();
instanceCache2.set(cls, instance);
return instance;
}
var InMemoryPersistence2 = class {
constructor() {
this.type = "NONE";
this.storage = {};
}
async _isAvailable() {
return true;
}
async _set(key, value) {
this.storage[key] = value;
}
async _get(key) {
const value = this.storage[key];
return value === void 0 ? null : value;
}
async _remove(key) {
delete this.storage[key];
}
_addListener(_key, _listener) {
return;
}
_removeListener(_key, _listener) {
return;
}
};
InMemoryPersistence2.type = "NONE";
var inMemoryPersistence2 = InMemoryPersistence2;
function _persistenceKeyName2(key, apiKey, appName) {
return `${"firebase"}:${key}:${apiKey}:${appName}`;
}
var PersistenceUserManager2 = class _PersistenceUserManager {
constructor(persistence, auth2, userKey) {
this.persistence = persistence;
this.auth = auth2;
this.userKey = userKey;
const { config, name: name7 } = this.auth;
this.fullUserKey = _persistenceKeyName2(this.userKey, config.apiKey, name7);
this.fullPersistenceKey = _persistenceKeyName2("persistence", config.apiKey, name7);
this.boundEventHandler = auth2._onStorageEvent.bind(auth2);
this.persistence._addListener(this.fullUserKey, this.boundEventHandler);
}
setCurrentUser(user) {
return this.persistence._set(this.fullUserKey, user.toJSON());
}
async getCurrentUser() {
const blob = await this.persistence._get(this.fullUserKey);
if (!blob) {
return null;
}
if (typeof blob === "string") {
const response = await getAccountInfo2(this.auth, { idToken: blob }).catch(() => void 0);
if (!response) {
return null;
}
return UserImpl2._fromGetAccountInfoResponse(this.auth, response, blob);
}
return UserImpl2._fromJSON(this.auth, blob);
}
removeCurrentUser() {
return this.persistence._remove(this.fullUserKey);
}
savePersistenceForRedirect() {
return this.persistence._set(this.fullPersistenceKey, this.persistence.type);
}
async setPersistence(newPersistence) {
if (this.persistence === newPersistence) {
return;
}
const currentUser = await this.getCurrentUser();
await this.removeCurrentUser();
this.persistence = newPersistence;
if (currentUser) {
return this.setCurrentUser(currentUser);
}
}
delete() {
this.persistence._removeListener(this.fullUserKey, this.boundEventHandler);
}
static async create(auth2, persistenceHierarchy, userKey = "authUser") {
if (!persistenceHierarchy.length) {
return new _PersistenceUserManager(_getInstance2(inMemoryPersistence2), auth2, userKey);
}
const availablePersistences = (await Promise.all(persistenceHierarchy.map(async (persistence) => {
if (await persistence._isAvailable()) {
return persistence;
}
return void 0;
}))).filter((persistence) => persistence);
let selectedPersistence = availablePersistences[0] || _getInstance2(inMemoryPersistence2);
const key = _persistenceKeyName2(userKey, auth2.config.apiKey, auth2.name);
let userToMigrate = null;
for (const persistence of persistenceHierarchy) {
try {
const blob = await persistence._get(key);
if (blob) {
let user;
if (typeof blob === "string") {
const response = await getAccountInfo2(auth2, {
idToken: blob
}).catch(() => void 0);
if (!response) {
break;
}
user = await UserImpl2._fromGetAccountInfoResponse(auth2, response, blob);
} else {
user = UserImpl2._fromJSON(auth2, blob);
}
if (persistence !== selectedPersistence) {
userToMigrate = user;
}
selectedPersistence = persistence;
break;
}
} catch {
}
}
const migrationHierarchy = availablePersistences.filter((p) => p._shouldAllowMigration);
if (!selectedPersistence._shouldAllowMigration || !migrationHierarchy.length) {
return new _PersistenceUserManager(selectedPersistence, auth2, userKey);
}
selectedPersistence = migrationHierarchy[0];
if (userToMigrate) {
await selectedPersistence._set(key, userToMigrate.toJSON());
}
await Promise.all(persistenceHierarchy.map(async (persistence) => {
if (persistence !== selectedPersistence) {
try {
await persistence._remove(key);
} catch {
}
}
}));
return new _PersistenceUserManager(selectedPersistence, auth2, userKey);
}
};
function _getBrowserName2(userAgent) {
const ua = userAgent.toLowerCase();
if (ua.includes("opera/") || ua.includes("opr/") || ua.includes("opios/")) {
return "Opera";
} else if (_isIEMobile2(ua)) {
return "IEMobile";
} else if (ua.includes("msie") || ua.includes("trident/")) {
return "IE";
} else if (ua.includes("edge/")) {
return "Edge";
} else if (_isFirefox2(ua)) {
return "Firefox";
} else if (ua.includes("silk/")) {
return "Silk";
} else if (_isBlackBerry2(ua)) {
return "Blackberry";
} else if (_isWebOS2(ua)) {
return "Webos";
} else if (_isSafari2(ua)) {
return "Safari";
} else if ((ua.includes("chrome/") || _isChromeIOS2(ua)) && !ua.includes("edge/")) {
return "Chrome";
} else if (_isAndroid2(ua)) {
return "Android";
} else {
const re = /([a-zA-Z\d\.]+)\/[a-zA-Z\d\.]*$/;
const matches = userAgent.match(re);
if (matches?.length === 2) {
return matches[1];
}
}
return "Other";
}
function _isFirefox2(ua = util.getUA()) {
return /firefox\//i.test(ua);
}
function _isSafari2(userAgent = util.getUA()) {
const ua = userAgent.toLowerCase();
return ua.includes("safari/") && !ua.includes("chrome/") && !ua.includes("crios/") && !ua.includes("android");
}
function _isChromeIOS2(ua = util.getUA()) {
return /crios\//i.test(ua);
}
function _isIEMobile2(ua = util.getUA()) {
return /iemobile/i.test(ua);
}
function _isAndroid2(ua = util.getUA()) {
return /android/i.test(ua);
}
function _isBlackBerry2(ua = util.getUA()) {
return /blackberry/i.test(ua);
}
function _isWebOS2(ua = util.getUA()) {
return /webos/i.test(ua);
}
function _isIOS(ua = util.getUA()) {
return /iphone|ipad|ipod/i.test(ua) || /macintosh/i.test(ua) && /mobile/i.test(ua);
}
function _isIOS7Or8(ua = util.getUA()) {
return /(iPad|iPhone|iPod).*OS 7_\d/i.test(ua) || /(iPad|iPhone|iPod).*OS 8_\d/i.test(ua);
}
function _isIE10() {
return util.isIE() && document.documentMode === 10;
}
function _isMobileBrowser(ua = util.getUA()) {
return _isIOS(ua) || _isAndroid2(ua) || _isWebOS2(ua) || _isBlackBerry2(ua) || /windows phone/i.test(ua) || _isIEMobile2(ua);
}
function _getClientVersion2(clientPlatform, frameworks = []) {
let reportedPlatform;
switch (clientPlatform) {
case "Browser":
reportedPlatform = _getBrowserName2(util.getUA());
break;
case "Worker":
reportedPlatform = `${_getBrowserName2(util.getUA())}-${clientPlatform}`;
break;
default:
reportedPlatform = clientPlatform;
}
const reportedFrameworks = frameworks.length ? frameworks.join(",") : "FirebaseCore-web";
return `${reportedPlatform}/${"JsCore"}/${app2.SDK_VERSION}/${reportedFrameworks}`;
}
var AuthMiddlewareQueue2 = class {
constructor(auth2) {
this.auth = auth2;
this.queue = [];
}
pushCallback(callback, onAbort) {
const wrappedCallback = (user) => new Promise((resolve, reject) => {
try {
const result = callback(user);
resolve(result);
} catch (e) {
reject(e);
}
});
wrappedCallback.onAbort = onAbort;
this.queue.push(wrappedCallback);
const index = this.queue.length - 1;
return () => {
this.queue[index] = () => Promise.resolve();
};
}
async runMiddleware(nextUser) {
if (this.auth.currentUser === nextUser) {
return;
}
const onAbortStack = [];
try {
for (const beforeStateCallback of this.queue) {
await beforeStateCallback(nextUser);
if (beforeStateCallback.onAbort) {
onAbortStack.push(beforeStateCallback.onAbort);
}
}
} catch (e) {
onAbortStack.reverse();
for (const onAbort of onAbortStack) {
try {
onAbort();
} catch (_) {
}
}
throw this.auth._errorFactory.create("login-blocked", {
originalMessage: e?.message
});
}
}
};
async function _getPasswordPolicy2(auth2, request = {}) {
return _performApiRequest2(auth2, "GET", "/v2/passwordPolicy", _addTidIfNecessary2(auth2, request));
}
var MINIMUM_MIN_PASSWORD_LENGTH2 = 6;
var PasswordPolicyImpl2 = class {
constructor(response) {
const responseOptions = response.customStrengthOptions;
this.customStrengthOptions = {};
this.customStrengthOptions.minPasswordLength = responseOptions.minPasswordLength ?? MINIMUM_MIN_PASSWORD_LENGTH2;
if (responseOptions.maxPasswordLength) {
this.customStrengthOptions.maxPasswordLength = responseOptions.maxPasswordLength;
}
if (responseOptions.containsLowercaseCharacter !== void 0) {
this.customStrengthOptions.containsLowercaseLetter = responseOptions.containsLowercaseCharacter;
}
if (responseOptions.containsUppercaseCharacter !== void 0) {
this.customStrengthOptions.containsUppercaseLetter = responseOptions.containsUppercaseCharacter;
}
if (responseOptions.containsNumericCharacter !== void 0) {
this.customStrengthOptions.containsNumericCharacter = responseOptions.containsNumericCharacter;
}
if (responseOptions.containsNonAlphanumericCharacter !== void 0) {
this.customStrengthOptions.containsNonAlphanumericCharacter = responseOptions.containsNonAlphanumericCharacter;
}
this.enforcementState = response.enforcementState;
if (this.enforcementState === "ENFORCEMENT_STATE_UNSPECIFIED") {
this.enforcementState = "OFF";
}
this.allowedNonAlphanumericCharacters = response.allowedNonAlphanumericCharacters?.join("") ?? "";
this.forceUpgradeOnSignin = response.forceUpgradeOnSignin ?? false;
this.schemaVersion = response.schemaVersion;
}
validatePassword(password) {
const status = {
isValid: true,
passwordPolicy: this
};
this.validatePasswordLengthOptions(password, status);
this.validatePasswordCharacterOptions(password, status);
status.isValid && (status.isValid = status.meetsMinPasswordLength ?? true);
status.isValid && (status.isValid = status.meetsMaxPasswordLength ?? true);
status.isValid && (status.isValid = status.containsLowercaseLetter ?? true);
status.isValid && (status.isValid = status.containsUppercaseLetter ?? true);
status.isValid && (status.isValid = status.containsNumericCharacter ?? true);
status.isValid && (status.isValid = status.containsNonAlphanumericCharacter ?? true);
return status;
}
/**
* Validates that the password meets the length options for the policy.
*
* @param password Password to validate.
* @param status Validation status.
*/
validatePasswordLengthOptions(password, status) {
const minPasswordLength = this.customStrengthOptions.minPasswordLength;
const maxPasswordLength = this.customStrengthOptions.maxPasswordLength;
if (minPasswordLength) {
status.meetsMinPasswordLength = password.length >= minPasswordLength;
}
if (maxPasswordLength) {
status.meetsMaxPasswordLength = password.length <= maxPasswordLength;
}
}
/**
* Validates that the password meets the character options for the policy.
*
* @param password Password to validate.
* @param status Validation status.
*/
validatePasswordCharacterOptions(password, status) {
this.updatePasswordCharacterOptionsStatuses(
status,
/* containsLowercaseCharacter= */
false,
/* containsUppercaseCharacter= */
false,
/* containsNumericCharacter= */
false,
/* containsNonAlphanumericCharacter= */
false
);
let passwordChar;
for (let i = 0; i < password.length; i++) {
passwordChar = password.charAt(i);
this.updatePasswordCharacterOptionsStatuses(
status,
/* containsLowercaseCharacter= */
passwordChar >= "a" && passwordChar <= "z",
/* containsUppercaseCharacter= */
passwordChar >= "A" && passwordChar <= "Z",
/* containsNumericCharacter= */
passwordChar >= "0" && passwordChar <= "9",
/* containsNonAlphanumericCharacter= */
this.allowedNonAlphanumericCharacters.includes(passwordChar)
);
}
}
/**
* Updates the running validation status with the statuses for the character options.
* Expected to be called each time a character is processed to update each option status
* based on the current character.
*
* @param status Validation status.
* @param containsLowercaseCharacter Whether the character is a lowercase letter.
* @param containsUppercaseCharacter Whether the character is an uppercase letter.
* @param containsNumericCharacter Whether the character is a numeric character.
* @param containsNonAlphanumericCharacter Whether the character is a non-alphanumeric character.
*/
updatePasswordCharacterOptionsStatuses(status, containsLowercaseCharacter, containsUppercaseCharacter, containsNumericCharacter, containsNonAlphanumericCharacter) {
if (this.customStrengthOptions.containsLowercaseLetter) {
status.containsLowercaseLetter || (status.containsLowercaseLetter = containsLowercaseCharacter);
}
if (this.customStrengthOptions.containsUppercaseLetter) {
status.containsUppercaseLetter || (status.containsUppercaseLetter = containsUppercaseCharacter);
}
if (this.customStrengthOptions.containsNumericCharacter) {
status.containsNumericCharacter || (status.containsNumericCharacter = containsNumericCharacter);
}
if (this.customStrengthOptions.containsNonAlphanumericCharacter) {
status.containsNonAlphanumericCharacter || (status.containsNonAlphanumericCharacter = containsNonAlphanumericCharacter);
}
}
};
var AuthImpl2 = class {
constructor(app3, heartbeatServiceProvider, appCheckServiceProvider, config) {
this.app = app3;
this.heartbeatServiceProvider = heartbeatServiceProvider;
this.appCheckServiceProvider = appCheckServiceProvider;
this.config = config;
this.currentUser = null;
this.emulatorConfig = null;
this.operations = Promise.resolve();
this.authStateSubscription = new Subscription2(this);
this.idTokenSubscription = new Subscription2(this);
this.beforeStateQueue = new AuthMiddlewareQueue2(this);
this.redirectUser = null;
this.isProactiveRefreshEnabled = false;
this.EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION = 1;
this._canInitEmulator = true;
this._isInitialized = false;
this._deleted = false;
this._initializationPromise = null;
this._popupRedirectResolver = null;
this._errorFactory = _DEFAULT_AUTH_ERROR_FACTORY2;
this._agentRecaptchaConfig = null;
this._tenantRecaptchaConfigs = {};
this._projectPasswordPolicy = null;
this._tenantPasswordPolicies = {};
this._resolvePersistenceManagerAvailable = void 0;
this.lastNotifiedUid = void 0;
this.languageCode = null;
this.tenantId = null;
this.settings = { appVerificationDisabledForTesting: false };
this.frameworks = [];
this.name = app3.name;
this.clientVersion = config.sdkClientVersion;
this._persistenceManagerAvailable = new Promise((resolve) => this._resolvePersistenceManagerAvailable = resolve);
}
_initializeWithPersistence(persistenceHierarchy, popupRedirectResolver) {
if (popupRedirectResolver) {
this._popupRedirectResolver = _getInstance2(popupRedirectResolver);
}
this._initializationPromise = this.queue(async () => {
if (this._deleted) {
return;
}
this.persistenceManager = await PersistenceUserManager2.create(this, persistenceHierarchy);
this._resolvePersistenceManagerAvailable?.();
if (this._deleted) {
return;
}
if (this._popupRedirectResolver?._shouldInitProactively) {
try {
await this._popupRedirectResolver._initialize(this);
} catch (e) {
}
}
await this.initializeCurrentUser(popupRedirectResolver);
this.lastNotifiedUid = this.currentUser?.uid || null;
if (this._deleted) {
return;
}
this._isInitialized = true;
});
return this._initializationPromise;
}
/**
* If the persistence is changed in another window, the user manager will let us know
*/
async _onStorageEvent() {
if (this._deleted) {
return;
}
const user = await this.assertedPersistence.getCurrentUser();
if (!this.currentUser && !user) {
return;
}
if (this.currentUser && user && this.currentUser.uid === user.uid) {
this._currentUser._assign(user);
await this.currentUser.getIdToken();
return;
}
await this._updateCurrentUser(
user,
/* skipBeforeStateCallbacks */
true
);
}
async initializeCurrentUserFromIdToken(idToken) {
try {
const response = await getAccountInfo2(this, { idToken });
const user = await UserImpl2._fromGetAccountInfoResponse(this, response, idToken);
await this.directlySetCurrentUser(user);
} catch (err) {
console.warn("FirebaseServerApp could not login user with provided authIdToken: ", err);
await this.directlySetCurrentUser(null);
}
}
async initializeCurrentUser(popupRedirectResolver) {
if (app2._isFirebaseServerApp(this.app)) {
const idToken = this.app.settings.authIdToken;
if (idToken) {
return new Promise((resolve) => {
setTimeout(() => this.initializeCurrentUserFromIdToken(idToken).then(resolve, resolve));
});
} else {
return this.directlySetCurrentUser(null);
}
}
const previouslyStoredUser = await this.assertedPersistence.getCurrentUser();
let futureCurrentUser = previouslyStoredUser;
let needsTocheckMiddleware = false;
if (popupRedirectResolver && this.config.authDomain) {
await this.getOrInitRedirectPersistenceManager();
const redirectUserEventId = this.redirectUser?._redirectEventId;
const storedUserEventId = futureCurrentUser?._redirectEventId;
const result = await this.tryRedirectSignIn(popupRedirectResolver);
if ((!redirectUserEventId || redirectUserEventId === storedUserEventId) && result?.user) {
futureCurrentUser = result.user;
needsTocheckMiddleware = true;
}
}
if (!futureCurrentUser) {
return this.directlySetCurrentUser(null);
}
if (!futureCurrentUser._redirectEventId) {
if (needsTocheckMiddleware) {
try {
await this.beforeStateQueue.runMiddleware(futureCurrentUser);
} catch (e) {
futureCurrentUser = previouslyStoredUser;
this._popupRedirectResolver._overrideRedirectResult(this, () => Promise.reject(e));
}
}
if (futureCurrentUser) {
return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
} else {
return this.directlySetCurrentUser(null);
}
}
_assert2(
this._popupRedirectResolver,
this,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
await this.getOrInitRedirectPersistenceManager();
if (this.redirectUser && this.redirectUser._redirectEventId === futureCurrentUser._redirectEventId) {
return this.directlySetCurrentUser(futureCurrentUser);
}
return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
}
async tryRedirectSignIn(redirectResolver) {
let result = null;
try {
result = await this._popupRedirectResolver._completeRedirectFn(this, redirectResolver, true);
} catch (e) {
await this._setRedirectUser(null);
}
return result;
}
async reloadAndSetCurrentUserOrClear(user) {
try {
await _reloadWithoutSaving2(user);
} catch (e) {
if (e?.code !== `auth/${"network-request-failed"}`) {
return this.directlySetCurrentUser(null);
}
}
return this.directlySetCurrentUser(user);
}
useDeviceLanguage() {
this.languageCode = _getUserLanguage2();
}
async _delete() {
this._deleted = true;
}
async updateCurrentUser(userExtern) {
if (app2._isFirebaseServerApp(this.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(this));
}
const user = userExtern ? util.getModularInstance(userExtern) : null;
if (user) {
_assert2(
user.auth.config.apiKey === this.config.apiKey,
this,
"invalid-user-token"
/* AuthErrorCode.INVALID_AUTH */
);
}
return this._updateCurrentUser(user && user._clone(this));
}
async _updateCurrentUser(user, skipBeforeStateCallbacks = false) {
if (this._deleted) {
return;
}
if (user) {
_assert2(
this.tenantId === user.tenantId,
this,
"tenant-id-mismatch"
/* AuthErrorCode.TENANT_ID_MISMATCH */
);
}
if (!skipBeforeStateCallbacks) {
await this.beforeStateQueue.runMiddleware(user);
}
return this.queue(async () => {
await this.directlySetCurrentUser(user);
this.notifyAuthListeners();
});
}
async signOut() {
if (app2._isFirebaseServerApp(this.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(this));
}
await this.beforeStateQueue.runMiddleware(null);
if (this.redirectPersistenceManager || this._popupRedirectResolver) {
await this._setRedirectUser(null);
}
return this._updateCurrentUser(
null,
/* skipBeforeStateCallbacks */
true
);
}
setPersistence(persistence) {
if (app2._isFirebaseServerApp(this.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(this));
}
return this.queue(async () => {
await this.assertedPersistence.setPersistence(_getInstance2(persistence));
});
}
_getRecaptchaConfig() {
if (this.tenantId == null) {
return this._agentRecaptchaConfig;
} else {
return this._tenantRecaptchaConfigs[this.tenantId];
}
}
async validatePassword(password) {
if (!this._getPasswordPolicyInternal()) {
await this._updatePasswordPolicy();
}
const passwordPolicy = this._getPasswordPolicyInternal();
if (passwordPolicy.schemaVersion !== this.EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION) {
return Promise.reject(this._errorFactory.create("unsupported-password-policy-schema-version", {}));
}
return passwordPolicy.validatePassword(password);
}
_getPasswordPolicyInternal() {
if (this.tenantId === null) {
return this._projectPasswordPolicy;
} else {
return this._tenantPasswordPolicies[this.tenantId];
}
}
async _updatePasswordPolicy() {
const response = await _getPasswordPolicy2(this);
const passwordPolicy = new PasswordPolicyImpl2(response);
if (this.tenantId === null) {
this._projectPasswordPolicy = passwordPolicy;
} else {
this._tenantPasswordPolicies[this.tenantId] = passwordPolicy;
}
}
_getPersistenceType() {
return this.assertedPersistence.persistence.type;
}
_getPersistence() {
return this.assertedPersistence.persistence;
}
_updateErrorMap(errorMap) {
this._errorFactory = new util.ErrorFactory("auth", "Firebase", errorMap());
}
onAuthStateChanged(nextOrObserver, error, completed) {
return this.registerStateListener(this.authStateSubscription, nextOrObserver, error, completed);
}
beforeAuthStateChanged(callback, onAbort) {
return this.beforeStateQueue.pushCallback(callback, onAbort);
}
onIdTokenChanged(nextOrObserver, error, completed) {
return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
}
authStateReady() {
return new Promise((resolve, reject) => {
if (this.currentUser) {
resolve();
} else {
const unsubscribe = this.onAuthStateChanged(() => {
unsubscribe();
resolve();
}, reject);
}
});
}
/**
* Revokes the given access token. Currently only supports Apple OAuth access tokens.
*/
async revokeAccessToken(token) {
if (this.currentUser) {
const idToken = await this.currentUser.getIdToken();
const request = {
providerId: "apple.com",
tokenType: "ACCESS_TOKEN",
token,
idToken
};
if (this.tenantId != null) {
request.tenantId = this.tenantId;
}
await revokeToken2(this, request);
}
}
toJSON() {
return {
apiKey: this.config.apiKey,
authDomain: this.config.authDomain,
appName: this.name,
currentUser: this._currentUser?.toJSON()
};
}
async _setRedirectUser(user, popupRedirectResolver) {
const redirectManager = await this.getOrInitRedirectPersistenceManager(popupRedirectResolver);
return user === null ? redirectManager.removeCurrentUser() : redirectManager.setCurrentUser(user);
}
async getOrInitRedirectPersistenceManager(popupRedirectResolver) {
if (!this.redirectPersistenceManager) {
const resolver = popupRedirectResolver && _getInstance2(popupRedirectResolver) || this._popupRedirectResolver;
_assert2(
resolver,
this,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
this.redirectPersistenceManager = await PersistenceUserManager2.create(
this,
[_getInstance2(resolver._redirectPersistence)],
"redirectUser"
/* KeyName.REDIRECT_USER */
);
this.redirectUser = await this.redirectPersistenceManager.getCurrentUser();
}
return this.redirectPersistenceManager;
}
async _redirectUserForId(id) {
if (this._isInitialized) {
await this.queue(async () => {
});
}
if (this._currentUser?._redirectEventId === id) {
return this._currentUser;
}
if (this.redirectUser?._redirectEventId === id) {
return this.redirectUser;
}
return null;
}
async _persistUserIfCurrent(user) {
if (user === this.currentUser) {
return this.queue(async () => this.directlySetCurrentUser(user));
}
}
/** Notifies listeners only if the user is current */
_notifyListenersIfCurrent(user) {
if (user === this.currentUser) {
this.notifyAuthListeners();
}
}
_key() {
return `${this.config.authDomain}:${this.config.apiKey}:${this.name}`;
}
_startProactiveRefresh() {
this.isProactiveRefreshEnabled = true;
if (this.currentUser) {
this._currentUser._startProactiveRefresh();
}
}
_stopProactiveRefresh() {
this.isProactiveRefreshEnabled = false;
if (this.currentUser) {
this._currentUser._stopProactiveRefresh();
}
}
/** Returns the current user cast as the internal type */
get _currentUser() {
return this.currentUser;
}
notifyAuthListeners() {
if (!this._isInitialized) {
return;
}
this.idTokenSubscription.next(this.currentUser);
const currentUid = this.currentUser?.uid ?? null;
if (this.lastNotifiedUid !== currentUid) {
this.lastNotifiedUid = currentUid;
this.authStateSubscription.next(this.currentUser);
}
}
registerStateListener(subscription, nextOrObserver, error, completed) {
if (this._deleted) {
return () => {
};
}
const cb = typeof nextOrObserver === "function" ? nextOrObserver : nextOrObserver.next.bind(nextOrObserver);
let isUnsubscribed = false;
const promise = this._isInitialized ? Promise.resolve() : this._initializationPromise;
_assert2(
promise,
this,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
promise.then(() => {
if (isUnsubscribed) {
return;
}
cb(this.currentUser);
});
if (typeof nextOrObserver === "function") {
const unsubscribe = subscription.addObserver(nextOrObserver, error, completed);
return () => {
isUnsubscribed = true;
unsubscribe();
};
} else {
const unsubscribe = subscription.addObserver(nextOrObserver);
return () => {
isUnsubscribed = true;
unsubscribe();
};
}
}
/**
* Unprotected (from race conditions) method to set the current user. This
* should only be called from within a queued callback. This is necessary
* because the queue shouldn't rely on another queued callback.
*/
async directlySetCurrentUser(user) {
if (this.currentUser && this.currentUser !== user) {
this._currentUser._stopProactiveRefresh();
}
if (user && this.isProactiveRefreshEnabled) {
user._startProactiveRefresh();
}
this.currentUser = user;
if (user) {
await this.assertedPersistence.setCurrentUser(user);
} else {
await this.assertedPersistence.removeCurrentUser();
}
}
queue(action) {
this.operations = this.operations.then(action, action);
return this.operations;
}
get assertedPersistence() {
_assert2(
this.persistenceManager,
this,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return this.persistenceManager;
}
_logFramework(framework) {
if (!framework || this.frameworks.includes(framework)) {
return;
}
this.frameworks.push(framework);
this.frameworks.sort();
this.clientVersion = _getClientVersion2(this.config.clientPlatform, this._getFrameworks());
}
_getFrameworks() {
return this.frameworks;
}
async _getAdditionalHeaders() {
const headers = {
[
"X-Client-Version"
/* HttpHeader.X_CLIENT_VERSION */
]: this.clientVersion
};
if (this.app.options.appId) {
headers[
"X-Firebase-gmpid"
/* HttpHeader.X_FIREBASE_GMPID */
] = this.app.options.appId;
}
const heartbeatsHeader = await this.heartbeatServiceProvider.getImmediate({
optional: true
})?.getHeartbeatsHeader();
if (heartbeatsHeader) {
headers[
"X-Firebase-Client"
/* HttpHeader.X_FIREBASE_CLIENT */
] = heartbeatsHeader;
}
const appCheckToken = await this._getAppCheckToken();
if (appCheckToken) {
headers[
"X-Firebase-AppCheck"
/* HttpHeader.X_FIREBASE_APP_CHECK */
] = appCheckToken;
}
return headers;
}
async _getAppCheckToken() {
if (app2._isFirebaseServerApp(this.app) && this.app.settings.appCheckToken) {
return this.app.settings.appCheckToken;
}
const appCheckTokenResult = await this.appCheckServiceProvider.getImmediate({ optional: true })?.getToken();
if (appCheckTokenResult?.error) {
_logWarn2(`Error while retrieving App Check token: ${appCheckTokenResult.error}`);
}
return appCheckTokenResult?.token;
}
};
function _castAuth2(auth2) {
return util.getModularInstance(auth2);
}
var Subscription2 = class {
constructor(auth2) {
this.auth = auth2;
this.observer = null;
this.addObserver = util.createSubscribe((observer) => this.observer = observer);
}
get next() {
_assert2(
this.observer,
this.auth,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return this.observer.next.bind(this.observer);
}
};
var externalJSProvider2 = {
async loadJS() {
throw new Error("Unable to load external scripts");
},
recaptchaV2Script: "",
recaptchaEnterpriseScript: "",
gapiScript: ""
};
function _loadJS2(url) {
return externalJSProvider2.loadJS(url);
}
function _recaptchaEnterpriseScriptUrl2() {
return externalJSProvider2.recaptchaEnterpriseScript;
}
var MockGreCAPTCHATopLevel2 = class {
constructor() {
this.enterprise = new MockGreCAPTCHA2();
}
ready(callback) {
callback();
}
execute(_siteKey, _options) {
return Promise.resolve("token");
}
render(_container, _parameters) {
return "";
}
};
var MockGreCAPTCHA2 = class {
ready(callback) {
callback();
}
execute(_siteKey, _options) {
return Promise.resolve("token");
}
render(_container, _parameters) {
return "";
}
};
var RECAPTCHA_ENTERPRISE_VERIFIER_TYPE2 = "recaptcha-enterprise";
var FAKE_TOKEN2 = "NO_RECAPTCHA";
var RecaptchaEnterpriseVerifier2 = class {
/**
*
* @param authExtern - The corresponding Firebase {@link Auth} instance.
*
*/
constructor(authExtern) {
this.type = RECAPTCHA_ENTERPRISE_VERIFIER_TYPE2;
this.auth = _castAuth2(authExtern);
}
/**
* Executes the verification process.
*
* @returns A Promise for a token that can be used to assert the validity of a request.
*/
async verify(action = "verify", forceRefresh = false) {
async function retrieveSiteKey(auth2) {
if (!forceRefresh) {
if (auth2.tenantId == null && auth2._agentRecaptchaConfig != null) {
return auth2._agentRecaptchaConfig.siteKey;
}
if (auth2.tenantId != null && auth2._tenantRecaptchaConfigs[auth2.tenantId] !== void 0) {
return auth2._tenantRecaptchaConfigs[auth2.tenantId].siteKey;
}
}
return new Promise(async (resolve, reject) => {
getRecaptchaConfig2(auth2, {
clientType: "CLIENT_TYPE_WEB",
version: "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
}).then((response) => {
if (response.recaptchaKey === void 0) {
reject(new Error("recaptcha Enterprise site key undefined"));
} else {
const config = new RecaptchaConfig2(response);
if (auth2.tenantId == null) {
auth2._agentRecaptchaConfig = config;
} else {
auth2._tenantRecaptchaConfigs[auth2.tenantId] = config;
}
return resolve(config.siteKey);
}
}).catch((error) => {
reject(error);
});
});
}
function retrieveRecaptchaToken(siteKey, resolve, reject) {
const grecaptcha = window.grecaptcha;
if (isEnterprise2(grecaptcha)) {
grecaptcha.enterprise.ready(() => {
grecaptcha.enterprise.execute(siteKey, { action }).then((token) => {
resolve(token);
}).catch(() => {
resolve(FAKE_TOKEN2);
});
});
} else {
reject(Error("No reCAPTCHA enterprise script loaded."));
}
}
if (this.auth.settings.appVerificationDisabledForTesting) {
const mockRecaptcha = new MockGreCAPTCHATopLevel2();
return mockRecaptcha.execute("siteKey", { action: "verify" });
}
return new Promise((resolve, reject) => {
retrieveSiteKey(this.auth).then((siteKey) => {
if (!forceRefresh && isEnterprise2(window.grecaptcha)) {
retrieveRecaptchaToken(siteKey, resolve, reject);
} else {
if (typeof window === "undefined") {
reject(new Error("RecaptchaVerifier is only supported in browser"));
return;
}
let url = _recaptchaEnterpriseScriptUrl2();
if (url.length !== 0) {
url += siteKey;
}
_loadJS2(url).then(() => {
retrieveRecaptchaToken(siteKey, resolve, reject);
}).catch((error) => {
reject(error);
});
}
}).catch((error) => {
reject(error);
});
});
}
};
async function injectRecaptchaFields2(auth2, request, action, isCaptchaResp = false, isFakeToken = false) {
const verifier = new RecaptchaEnterpriseVerifier2(auth2);
let captchaResponse;
if (isFakeToken) {
captchaResponse = FAKE_TOKEN2;
} else {
try {
captchaResponse = await verifier.verify(action);
} catch (error) {
captchaResponse = await verifier.verify(action, true);
}
}
const newRequest = { ...request };
if (action === "mfaSmsEnrollment" || action === "mfaSmsSignIn") {
if ("phoneEnrollmentInfo" in newRequest) {
const phoneNumber = newRequest.phoneEnrollmentInfo.phoneNumber;
const recaptchaToken = newRequest.phoneEnrollmentInfo.recaptchaToken;
Object.assign(newRequest, {
"phoneEnrollmentInfo": {
phoneNumber,
recaptchaToken,
captchaResponse,
"clientType": "CLIENT_TYPE_WEB",
"recaptchaVersion": "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
}
});
} else if ("phoneSignInInfo" in newRequest) {
const recaptchaToken = newRequest.phoneSignInInfo.recaptchaToken;
Object.assign(newRequest, {
"phoneSignInInfo": {
recaptchaToken,
captchaResponse,
"clientType": "CLIENT_TYPE_WEB",
"recaptchaVersion": "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
}
});
}
return newRequest;
}
if (!isCaptchaResp) {
Object.assign(newRequest, { captchaResponse });
} else {
Object.assign(newRequest, { "captchaResp": captchaResponse });
}
Object.assign(newRequest, {
"clientType": "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
});
Object.assign(newRequest, {
"recaptchaVersion": "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
});
return newRequest;
}
async function handleRecaptchaFlow2(authInstance, request, actionName, actionMethod, recaptchaAuthProvider) {
if (recaptchaAuthProvider === "EMAIL_PASSWORD_PROVIDER") {
if (authInstance._getRecaptchaConfig()?.isProviderEnabled(
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
)) {
const requestWithRecaptcha = await injectRecaptchaFields2(
authInstance,
request,
actionName,
actionName === "getOobCode"
/* RecaptchaActionName.GET_OOB_CODE */
);
return actionMethod(authInstance, requestWithRecaptcha);
} else {
return actionMethod(authInstance, request).catch(async (error) => {
if (error.code === `auth/${"missing-recaptcha-token"}`) {
console.log(`${actionName} is protected by reCAPTCHA Enterprise for this project. Automatically triggering the reCAPTCHA flow and restarting the flow.`);
const requestWithRecaptcha = await injectRecaptchaFields2(
authInstance,
request,
actionName,
actionName === "getOobCode"
/* RecaptchaActionName.GET_OOB_CODE */
);
return actionMethod(authInstance, requestWithRecaptcha);
} else {
return Promise.reject(error);
}
});
}
} else if (recaptchaAuthProvider === "PHONE_PROVIDER") {
if (authInstance._getRecaptchaConfig()?.isProviderEnabled(
"PHONE_PROVIDER"
/* RecaptchaAuthProvider.PHONE_PROVIDER */
)) {
const requestWithRecaptcha = await injectRecaptchaFields2(authInstance, request, actionName);
return actionMethod(authInstance, requestWithRecaptcha).catch(async (error) => {
if (authInstance._getRecaptchaConfig()?.getProviderEnforcementState(
"PHONE_PROVIDER"
/* RecaptchaAuthProvider.PHONE_PROVIDER */
) === "AUDIT") {
if (error.code === `auth/${"missing-recaptcha-token"}` || error.code === `auth/${"invalid-app-credential"}`) {
console.log(`Failed to verify with reCAPTCHA Enterprise. Automatically triggering the reCAPTCHA v2 flow to complete the ${actionName} flow.`);
const requestWithRecaptchaFields = await injectRecaptchaFields2(
authInstance,
request,
actionName,
false,
// isCaptchaResp
true
// isFakeToken
);
return actionMethod(authInstance, requestWithRecaptchaFields);
}
}
return Promise.reject(error);
});
} else {
const requestWithRecaptchaFields = await injectRecaptchaFields2(
authInstance,
request,
actionName,
false,
// isCaptchaResp
true
// isFakeToken
);
return actionMethod(authInstance, requestWithRecaptchaFields);
}
} else {
return Promise.reject(recaptchaAuthProvider + " provider is not supported.");
}
}
async function _initializeRecaptchaConfig2(auth2) {
const authInternal = _castAuth2(auth2);
const response = await getRecaptchaConfig2(authInternal, {
clientType: "CLIENT_TYPE_WEB",
version: "RECAPTCHA_ENTERPRISE"
/* RecaptchaVersion.ENTERPRISE */
});
const config = new RecaptchaConfig2(response);
if (authInternal.tenantId == null) {
authInternal._agentRecaptchaConfig = config;
} else {
authInternal._tenantRecaptchaConfigs[authInternal.tenantId] = config;
}
if (config.isAnyProviderEnabled()) {
const verifier = new RecaptchaEnterpriseVerifier2(authInternal);
void verifier.verify();
}
}
function initializeAuth2(app$1, deps) {
const provider = app2._getProvider(app$1, "auth");
if (provider.isInitialized()) {
const auth3 = provider.getImmediate();
const initialOptions = provider.getOptions();
if (util.deepEqual(initialOptions, deps ?? {})) {
return auth3;
} else {
_fail2(
auth3,
"already-initialized"
/* AuthErrorCode.ALREADY_INITIALIZED */
);
}
}
const auth2 = provider.initialize({ options: deps });
return auth2;
}
function _initializeAuthInstance2(auth2, deps) {
const persistence = deps?.persistence || [];
const hierarchy = (Array.isArray(persistence) ? persistence : [persistence]).map(_getInstance2);
if (deps?.errorMap) {
auth2._updateErrorMap(deps.errorMap);
}
auth2._initializeWithPersistence(hierarchy, deps?.popupRedirectResolver);
}
function connectAuthEmulator2(auth2, url, options) {
const authInternal = _castAuth2(auth2);
_assert2(
/^https?:\/\//.test(url),
authInternal,
"invalid-emulator-scheme"
/* AuthErrorCode.INVALID_EMULATOR_SCHEME */
);
const disableWarnings = !!options?.disableWarnings;
const protocol = extractProtocol2(url);
const { host, port } = extractHostAndPort2(url);
const portStr = port === null ? "" : `:${port}`;
const emulator = { url: `${protocol}//${host}${portStr}/` };
const emulatorConfig = Object.freeze({
host,
port,
protocol: protocol.replace(":", ""),
options: Object.freeze({ disableWarnings })
});
if (!authInternal._canInitEmulator) {
_assert2(
authInternal.config.emulator && authInternal.emulatorConfig,
authInternal,
"emulator-config-failed"
/* AuthErrorCode.EMULATOR_CONFIG_FAILED */
);
_assert2(
util.deepEqual(emulator, authInternal.config.emulator) && util.deepEqual(emulatorConfig, authInternal.emulatorConfig),
authInternal,
"emulator-config-failed"
/* AuthErrorCode.EMULATOR_CONFIG_FAILED */
);
return;
}
authInternal.config.emulator = emulator;
authInternal.emulatorConfig = emulatorConfig;
authInternal.settings.appVerificationDisabledForTesting = true;
if (util.isCloudWorkstation(host)) {
void util.pingServer(`${protocol}//${host}${portStr}`);
util.updateEmulatorBanner("Auth", true);
} else if (!disableWarnings) {
emitEmulatorWarning2();
}
}
function extractProtocol2(url) {
const protocolEnd = url.indexOf(":");
return protocolEnd < 0 ? "" : url.substr(0, protocolEnd + 1);
}
function extractHostAndPort2(url) {
const protocol = extractProtocol2(url);
const authority = /(\/\/)?([^?#/]+)/.exec(url.substr(protocol.length));
if (!authority) {
return { host: "", port: null };
}
const hostAndPort = authority[2].split("@").pop() || "";
const bracketedIPv6 = /^(\[[^\]]+\])(:|$)/.exec(hostAndPort);
if (bracketedIPv6) {
const host = bracketedIPv6[1];
return { host, port: parsePort2(hostAndPort.substr(host.length + 1)) };
} else {
const [host, port] = hostAndPort.split(":");
return { host, port: parsePort2(port) };
}
}
function parsePort2(portStr) {
if (!portStr) {
return null;
}
const port = Number(portStr);
if (isNaN(port)) {
return null;
}
return port;
}
function emitEmulatorWarning2() {
function attachBanner() {
const el = document.createElement("p");
const sty = el.style;
el.innerText = "Running in emulator mode. Do not use with production credentials.";
sty.position = "fixed";
sty.width = "100%";
sty.backgroundColor = "#ffffff";
sty.border = ".1em solid #000000";
sty.color = "#b50000";
sty.bottom = "0px";
sty.left = "0px";
sty.margin = "0px";
sty.zIndex = "10000";
sty.textAlign = "center";
el.classList.add("firebase-emulator-warning");
document.body.appendChild(el);
}
if (typeof console !== "undefined" && typeof console.info === "function") {
console.info("WARNING: You are using the Auth Emulator, which is intended for local testing only. Do not use with production credentials.");
}
if (typeof window !== "undefined" && typeof document !== "undefined") {
if (document.readyState === "loading") {
window.addEventListener("DOMContentLoaded", attachBanner);
} else {
attachBanner();
}
}
}
var AuthCredential2 = class {
/** @internal */
constructor(providerId, signInMethod) {
this.providerId = providerId;
this.signInMethod = signInMethod;
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns a JSON-serializable representation of this object.
*/
toJSON() {
return debugFail2("not implemented");
}
/** @internal */
_getIdTokenResponse(_auth) {
return debugFail2("not implemented");
}
/** @internal */
_linkToIdToken(_auth, _idToken) {
return debugFail2("not implemented");
}
/** @internal */
_getReauthenticationResolver(_auth) {
return debugFail2("not implemented");
}
};
async function resetPassword2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:resetPassword", _addTidIfNecessary2(auth2, request));
}
async function updateEmailPassword2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:update", request);
}
async function linkEmailPassword2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:signUp", request);
}
async function applyActionCode$12(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:update", _addTidIfNecessary2(auth2, request));
}
async function signInWithPassword2(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithPassword", _addTidIfNecessary2(auth2, request));
}
async function sendOobCode2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:sendOobCode", _addTidIfNecessary2(auth2, request));
}
async function sendEmailVerification$12(auth2, request) {
return sendOobCode2(auth2, request);
}
async function sendPasswordResetEmail$12(auth2, request) {
return sendOobCode2(auth2, request);
}
async function sendSignInLinkToEmail$12(auth2, request) {
return sendOobCode2(auth2, request);
}
async function verifyAndChangeEmail2(auth2, request) {
return sendOobCode2(auth2, request);
}
async function signInWithEmailLink$12(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithEmailLink", _addTidIfNecessary2(auth2, request));
}
async function signInWithEmailLinkForLinking2(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithEmailLink", _addTidIfNecessary2(auth2, request));
}
var EmailAuthCredential2 = class _EmailAuthCredential extends AuthCredential2 {
/** @internal */
constructor(_email, _password, signInMethod, _tenantId = null) {
super("password", signInMethod);
this._email = _email;
this._password = _password;
this._tenantId = _tenantId;
}
/** @internal */
static _fromEmailAndPassword(email, password) {
return new _EmailAuthCredential(
email,
password,
"password"
/* SignInMethod.EMAIL_PASSWORD */
);
}
/** @internal */
static _fromEmailAndCode(email, oobCode, tenantId = null) {
return new _EmailAuthCredential(email, oobCode, "emailLink", tenantId);
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
return {
email: this._email,
password: this._password,
signInMethod: this.signInMethod,
tenantId: this._tenantId
};
}
/**
* Static method to deserialize a JSON representation of an object into an {@link AuthCredential}.
*
* @param json - Either `object` or the stringified representation of the object. When string is
* provided, `JSON.parse` would be called first.
*
* @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
*/
static fromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
if (obj?.email && obj?.password) {
if (obj.signInMethod === "password") {
return this._fromEmailAndPassword(obj.email, obj.password);
} else if (obj.signInMethod === "emailLink") {
return this._fromEmailAndCode(obj.email, obj.password, obj.tenantId);
}
}
return null;
}
/** @internal */
async _getIdTokenResponse(auth2) {
switch (this.signInMethod) {
case "password":
const request = {
returnSecureToken: true,
email: this._email,
password: this._password,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
return handleRecaptchaFlow2(
auth2,
request,
"signInWithPassword",
signInWithPassword2,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
case "emailLink":
return signInWithEmailLink$12(auth2, {
email: this._email,
oobCode: this._password
});
default:
_fail2(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
}
/** @internal */
async _linkToIdToken(auth2, idToken) {
switch (this.signInMethod) {
case "password":
const request = {
idToken,
returnSecureToken: true,
email: this._email,
password: this._password,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
return handleRecaptchaFlow2(
auth2,
request,
"signUpPassword",
linkEmailPassword2,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
case "emailLink":
return signInWithEmailLinkForLinking2(auth2, {
idToken,
email: this._email,
oobCode: this._password
});
default:
_fail2(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
}
/** @internal */
_getReauthenticationResolver(auth2) {
return this._getIdTokenResponse(auth2);
}
};
async function signInWithIdp2(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithIdp", _addTidIfNecessary2(auth2, request));
}
var IDP_REQUEST_URI$12 = "http://localhost";
var OAuthCredential2 = class _OAuthCredential extends AuthCredential2 {
constructor() {
super(...arguments);
this.pendingToken = null;
}
/** @internal */
static _fromParams(params) {
const cred = new _OAuthCredential(params.providerId, params.signInMethod);
if (params.idToken || params.accessToken) {
if (params.idToken) {
cred.idToken = params.idToken;
}
if (params.accessToken) {
cred.accessToken = params.accessToken;
}
if (params.nonce && !params.pendingToken) {
cred.nonce = params.nonce;
}
if (params.pendingToken) {
cred.pendingToken = params.pendingToken;
}
} else if (params.oauthToken && params.oauthTokenSecret) {
cred.accessToken = params.oauthToken;
cred.secret = params.oauthTokenSecret;
} else {
_fail2(
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
}
return cred;
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
return {
idToken: this.idToken,
accessToken: this.accessToken,
secret: this.secret,
nonce: this.nonce,
pendingToken: this.pendingToken,
providerId: this.providerId,
signInMethod: this.signInMethod
};
}
/**
* Static method to deserialize a JSON representation of an object into an
* {@link AuthCredential}.
*
* @param json - Input can be either Object or the stringified representation of the object.
* When string is provided, JSON.parse would be called first.
*
* @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
*/
static fromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
const { providerId, signInMethod, ...rest } = obj;
if (!providerId || !signInMethod) {
return null;
}
const cred = new _OAuthCredential(providerId, signInMethod);
cred.idToken = rest.idToken || void 0;
cred.accessToken = rest.accessToken || void 0;
cred.secret = rest.secret;
cred.nonce = rest.nonce;
cred.pendingToken = rest.pendingToken || null;
return cred;
}
/** @internal */
_getIdTokenResponse(auth2) {
const request = this.buildRequest();
return signInWithIdp2(auth2, request);
}
/** @internal */
_linkToIdToken(auth2, idToken) {
const request = this.buildRequest();
request.idToken = idToken;
return signInWithIdp2(auth2, request);
}
/** @internal */
_getReauthenticationResolver(auth2) {
const request = this.buildRequest();
request.autoCreate = false;
return signInWithIdp2(auth2, request);
}
buildRequest() {
const request = {
requestUri: IDP_REQUEST_URI$12,
returnSecureToken: true
};
if (this.pendingToken) {
request.pendingToken = this.pendingToken;
} else {
const postBody = {};
if (this.idToken) {
postBody["id_token"] = this.idToken;
}
if (this.accessToken) {
postBody["access_token"] = this.accessToken;
}
if (this.secret) {
postBody["oauth_token_secret"] = this.secret;
}
postBody["providerId"] = this.providerId;
if (this.nonce && !this.pendingToken) {
postBody["nonce"] = this.nonce;
}
request.postBody = util.querystring(postBody);
}
return request;
}
};
async function signInWithPhoneNumber$12(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithPhoneNumber", _addTidIfNecessary2(auth2, request));
}
async function linkWithPhoneNumber$12(auth2, request) {
const response = await _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithPhoneNumber", _addTidIfNecessary2(auth2, request));
if (response.temporaryProof) {
throw _makeTaggedError2(auth2, "account-exists-with-different-credential", response);
}
return response;
}
var VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_2 = {
[
"USER_NOT_FOUND"
/* ServerError.USER_NOT_FOUND */
]: "user-not-found"
/* AuthErrorCode.USER_DELETED */
};
async function verifyPhoneNumberForExisting2(auth2, request) {
const apiRequest = {
...request,
operation: "REAUTH"
};
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithPhoneNumber", _addTidIfNecessary2(auth2, apiRequest), VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_2);
}
var PhoneAuthCredential2 = class _PhoneAuthCredential extends AuthCredential2 {
constructor(params) {
super(
"phone",
"phone"
/* SignInMethod.PHONE */
);
this.params = params;
}
/** @internal */
static _fromVerification(verificationId, verificationCode) {
return new _PhoneAuthCredential({ verificationId, verificationCode });
}
/** @internal */
static _fromTokenResponse(phoneNumber, temporaryProof) {
return new _PhoneAuthCredential({ phoneNumber, temporaryProof });
}
/** @internal */
_getIdTokenResponse(auth2) {
return signInWithPhoneNumber$12(auth2, this._makeVerificationRequest());
}
/** @internal */
_linkToIdToken(auth2, idToken) {
return linkWithPhoneNumber$12(auth2, {
idToken,
...this._makeVerificationRequest()
});
}
/** @internal */
_getReauthenticationResolver(auth2) {
return verifyPhoneNumberForExisting2(auth2, this._makeVerificationRequest());
}
/** @internal */
_makeVerificationRequest() {
const { temporaryProof, phoneNumber, verificationId, verificationCode } = this.params;
if (temporaryProof && phoneNumber) {
return { temporaryProof, phoneNumber };
}
return {
sessionInfo: verificationId,
code: verificationCode
};
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
const obj = {
providerId: this.providerId
};
if (this.params.phoneNumber) {
obj.phoneNumber = this.params.phoneNumber;
}
if (this.params.temporaryProof) {
obj.temporaryProof = this.params.temporaryProof;
}
if (this.params.verificationCode) {
obj.verificationCode = this.params.verificationCode;
}
if (this.params.verificationId) {
obj.verificationId = this.params.verificationId;
}
return obj;
}
/** Generates a phone credential based on a plain object or a JSON string. */
static fromJSON(json) {
if (typeof json === "string") {
json = JSON.parse(json);
}
const { verificationId, verificationCode, phoneNumber, temporaryProof } = json;
if (!verificationCode && !verificationId && !phoneNumber && !temporaryProof) {
return null;
}
return new _PhoneAuthCredential({
verificationId,
verificationCode,
phoneNumber,
temporaryProof
});
}
};
function parseMode2(mode) {
switch (mode) {
case "recoverEmail":
return "RECOVER_EMAIL";
case "resetPassword":
return "PASSWORD_RESET";
case "signIn":
return "EMAIL_SIGNIN";
case "verifyEmail":
return "VERIFY_EMAIL";
case "verifyAndChangeEmail":
return "VERIFY_AND_CHANGE_EMAIL";
case "revertSecondFactorAddition":
return "REVERT_SECOND_FACTOR_ADDITION";
default:
return null;
}
}
function parseDeepLink2(url) {
const link = util.querystringDecode(util.extractQuerystring(url))["link"];
const doubleDeepLink = link ? util.querystringDecode(util.extractQuerystring(link))["deep_link_id"] : null;
const iOSDeepLink = util.querystringDecode(util.extractQuerystring(url))["deep_link_id"];
const iOSDoubleDeepLink = iOSDeepLink ? util.querystringDecode(util.extractQuerystring(iOSDeepLink))["link"] : null;
return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
}
var ActionCodeURL2 = class _ActionCodeURL {
/**
* @param actionLink - The link from which to extract the URL.
* @returns The {@link ActionCodeURL} object, or null if the link is invalid.
*
* @internal
*/
constructor(actionLink) {
const searchParams = util.querystringDecode(util.extractQuerystring(actionLink));
const apiKey = searchParams[
"apiKey"
/* QueryField.API_KEY */
] ?? null;
const code = searchParams[
"oobCode"
/* QueryField.CODE */
] ?? null;
const operation = parseMode2(searchParams[
"mode"
/* QueryField.MODE */
] ?? null);
_assert2(
apiKey && code && operation,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
this.apiKey = apiKey;
this.operation = operation;
this.code = code;
this.continueUrl = searchParams[
"continueUrl"
/* QueryField.CONTINUE_URL */
] ?? null;
this.languageCode = searchParams[
"lang"
/* QueryField.LANGUAGE_CODE */
] ?? null;
this.tenantId = searchParams[
"tenantId"
/* QueryField.TENANT_ID */
] ?? null;
}
/**
* Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid,
* otherwise returns null.
*
* @param link - The email action link string.
* @returns The {@link ActionCodeURL} object, or null if the link is invalid.
*
* @public
*/
static parseLink(link) {
const actionLink = parseDeepLink2(link);
try {
return new _ActionCodeURL(actionLink);
} catch {
return null;
}
}
};
function parseActionCodeURL2(link) {
return ActionCodeURL2.parseLink(link);
}
var EmailAuthProvider2 = class _EmailAuthProvider {
constructor() {
this.providerId = _EmailAuthProvider.PROVIDER_ID;
}
/**
* Initialize an {@link AuthCredential} using an email and password.
*
* @example
* ```javascript
* const authCredential = EmailAuthProvider.credential(email, password);
* const userCredential = await signInWithCredential(auth, authCredential);
* ```
*
* @example
* ```javascript
* const userCredential = await signInWithEmailAndPassword(auth, email, password);
* ```
*
* @param email - Email address.
* @param password - User account password.
* @returns The auth provider credential.
*/
static credential(email, password) {
return EmailAuthCredential2._fromEmailAndPassword(email, password);
}
/**
* Initialize an {@link AuthCredential} using an email and an email link after a sign in with
* email link operation.
*
* @example
* ```javascript
* const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink);
* const userCredential = await signInWithCredential(auth, authCredential);
* ```
*
* @example
* ```javascript
* await sendSignInLinkToEmail(auth, email);
* // Obtain emailLink from user.
* const userCredential = await signInWithEmailLink(auth, email, emailLink);
* ```
*
* @param auth - The {@link Auth} instance used to verify the link.
* @param email - Email address.
* @param emailLink - Sign-in email link.
* @returns - The auth provider credential.
*/
static credentialWithLink(email, emailLink) {
const actionCodeUrl = ActionCodeURL2.parseLink(emailLink);
_assert2(
actionCodeUrl,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return EmailAuthCredential2._fromEmailAndCode(email, actionCodeUrl.code, actionCodeUrl.tenantId);
}
};
EmailAuthProvider2.PROVIDER_ID = "password";
EmailAuthProvider2.EMAIL_PASSWORD_SIGN_IN_METHOD = "password";
EmailAuthProvider2.EMAIL_LINK_SIGN_IN_METHOD = "emailLink";
var FederatedAuthProvider2 = class {
/**
* Constructor for generic OAuth providers.
*
* @param providerId - Provider for which credentials should be generated.
*/
constructor(providerId) {
this.providerId = providerId;
this.defaultLanguageCode = null;
this.customParameters = {};
}
/**
* Set the language gode.
*
* @param languageCode - language code
*/
setDefaultLanguage(languageCode) {
this.defaultLanguageCode = languageCode;
}
/**
* Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in
* operations.
*
* @remarks
* For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`,
* `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored.
*
* @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request.
*/
setCustomParameters(customOAuthParameters) {
this.customParameters = customOAuthParameters;
return this;
}
/**
* Retrieve the current list of {@link CustomParameters}.
*/
getCustomParameters() {
return this.customParameters;
}
};
var BaseOAuthProvider2 = class extends FederatedAuthProvider2 {
constructor() {
super(...arguments);
this.scopes = [];
}
/**
* Add an OAuth scope to the credential.
*
* @param scope - Provider OAuth scope to add.
*/
addScope(scope) {
if (!this.scopes.includes(scope)) {
this.scopes.push(scope);
}
return this;
}
/**
* Retrieve the current list of OAuth scopes.
*/
getScopes() {
return [...this.scopes];
}
};
var OAuthProvider2 = class _OAuthProvider extends BaseOAuthProvider2 {
/**
* Creates an {@link OAuthCredential} from a JSON string or a plain object.
* @param json - A plain object or a JSON string
*/
static credentialFromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
_assert2(
"providerId" in obj && "signInMethod" in obj,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return OAuthCredential2._fromParams(obj);
}
/**
* Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token.
*
* @remarks
* The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of
* the raw nonce must match the nonce field in the ID token.
*
* @example
* ```javascript
* // `googleUser` from the onsuccess Google Sign In callback.
* // Initialize a generate OAuth provider with a `google.com` providerId.
* const provider = new OAuthProvider('google.com');
* const credential = provider.credential({
* idToken: googleUser.getAuthResponse().id_token,
* });
* const result = await signInWithCredential(credential);
* ```
*
* @param params - Either the options object containing the ID token, access token and raw nonce
* or the ID token string.
*/
credential(params) {
return this._credential({ ...params, nonce: params.rawNonce });
}
/** An internal credential method that accepts more permissive options */
_credential(params) {
_assert2(
params.idToken || params.accessToken,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return OAuthCredential2._fromParams({
...params,
providerId: this.providerId,
signInMethod: this.providerId
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _OAuthProvider.oauthCredentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _OAuthProvider.oauthCredentialFromTaggedObject(error.customData || {});
}
static oauthCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { oauthIdToken, oauthAccessToken, oauthTokenSecret, pendingToken, nonce, providerId } = tokenResponse;
if (!oauthAccessToken && !oauthTokenSecret && !oauthIdToken && !pendingToken) {
return null;
}
if (!providerId) {
return null;
}
try {
return new _OAuthProvider(providerId)._credential({
idToken: oauthIdToken,
accessToken: oauthAccessToken,
nonce,
pendingToken
});
} catch (e) {
return null;
}
}
};
var FacebookAuthProvider2 = class _FacebookAuthProvider extends BaseOAuthProvider2 {
constructor() {
super(
"facebook.com"
/* ProviderId.FACEBOOK */
);
}
/**
* Creates a credential for Facebook.
*
* @example
* ```javascript
* // `event` from the Facebook auth.authResponseChange callback.
* const credential = FacebookAuthProvider.credential(event.authResponse.accessToken);
* const result = await signInWithCredential(credential);
* ```
*
* @param accessToken - Facebook access token.
*/
static credential(accessToken) {
return OAuthCredential2._fromParams({
providerId: _FacebookAuthProvider.PROVIDER_ID,
signInMethod: _FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD,
accessToken
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _FacebookAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _FacebookAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse || !("oauthAccessToken" in tokenResponse)) {
return null;
}
if (!tokenResponse.oauthAccessToken) {
return null;
}
try {
return _FacebookAuthProvider.credential(tokenResponse.oauthAccessToken);
} catch {
return null;
}
}
};
FacebookAuthProvider2.FACEBOOK_SIGN_IN_METHOD = "facebook.com";
FacebookAuthProvider2.PROVIDER_ID = "facebook.com";
var GoogleAuthProvider2 = class _GoogleAuthProvider extends BaseOAuthProvider2 {
constructor() {
super(
"google.com"
/* ProviderId.GOOGLE */
);
this.addScope("profile");
}
/**
* Creates a credential for Google. At least one of ID token and access token is required.
*
* @example
* ```javascript
* // \`googleUser\` from the onsuccess Google Sign In callback.
* const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
* const result = await signInWithCredential(credential);
* ```
*
* @param idToken - Google ID token.
* @param accessToken - Google access token.
*/
static credential(idToken, accessToken) {
return OAuthCredential2._fromParams({
providerId: _GoogleAuthProvider.PROVIDER_ID,
signInMethod: _GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD,
idToken,
accessToken
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _GoogleAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _GoogleAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { oauthIdToken, oauthAccessToken } = tokenResponse;
if (!oauthIdToken && !oauthAccessToken) {
return null;
}
try {
return _GoogleAuthProvider.credential(oauthIdToken, oauthAccessToken);
} catch {
return null;
}
}
};
GoogleAuthProvider2.GOOGLE_SIGN_IN_METHOD = "google.com";
GoogleAuthProvider2.PROVIDER_ID = "google.com";
var GithubAuthProvider2 = class _GithubAuthProvider extends BaseOAuthProvider2 {
constructor() {
super(
"github.com"
/* ProviderId.GITHUB */
);
}
/**
* Creates a credential for GitHub.
*
* @param accessToken - GitHub access token.
*/
static credential(accessToken) {
return OAuthCredential2._fromParams({
providerId: _GithubAuthProvider.PROVIDER_ID,
signInMethod: _GithubAuthProvider.GITHUB_SIGN_IN_METHOD,
accessToken
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _GithubAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _GithubAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse || !("oauthAccessToken" in tokenResponse)) {
return null;
}
if (!tokenResponse.oauthAccessToken) {
return null;
}
try {
return _GithubAuthProvider.credential(tokenResponse.oauthAccessToken);
} catch {
return null;
}
}
};
GithubAuthProvider2.GITHUB_SIGN_IN_METHOD = "github.com";
GithubAuthProvider2.PROVIDER_ID = "github.com";
var IDP_REQUEST_URI2 = "http://localhost";
var SAMLAuthCredential2 = class _SAMLAuthCredential extends AuthCredential2 {
/** @internal */
constructor(providerId, pendingToken) {
super(providerId, providerId);
this.pendingToken = pendingToken;
}
/** @internal */
_getIdTokenResponse(auth2) {
const request = this.buildRequest();
return signInWithIdp2(auth2, request);
}
/** @internal */
_linkToIdToken(auth2, idToken) {
const request = this.buildRequest();
request.idToken = idToken;
return signInWithIdp2(auth2, request);
}
/** @internal */
_getReauthenticationResolver(auth2) {
const request = this.buildRequest();
request.autoCreate = false;
return signInWithIdp2(auth2, request);
}
/** {@inheritdoc AuthCredential.toJSON} */
toJSON() {
return {
signInMethod: this.signInMethod,
providerId: this.providerId,
pendingToken: this.pendingToken
};
}
/**
* Static method to deserialize a JSON representation of an object into an
* {@link AuthCredential}.
*
* @param json - Input can be either Object or the stringified representation of the object.
* When string is provided, JSON.parse would be called first.
*
* @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
*/
static fromJSON(json) {
const obj = typeof json === "string" ? JSON.parse(json) : json;
const { providerId, signInMethod, pendingToken } = obj;
if (!providerId || !signInMethod || !pendingToken || providerId !== signInMethod) {
return null;
}
return new _SAMLAuthCredential(providerId, pendingToken);
}
/**
* Helper static method to avoid exposing the constructor to end users.
*
* @internal
*/
static _create(providerId, pendingToken) {
return new _SAMLAuthCredential(providerId, pendingToken);
}
buildRequest() {
return {
requestUri: IDP_REQUEST_URI2,
returnSecureToken: true,
pendingToken: this.pendingToken
};
}
};
var SAML_PROVIDER_PREFIX2 = "saml.";
var SAMLAuthProvider2 = class _SAMLAuthProvider extends FederatedAuthProvider2 {
/**
* Constructor. The providerId must start with "saml."
* @param providerId - SAML provider ID.
*/
constructor(providerId) {
_assert2(
providerId.startsWith(SAML_PROVIDER_PREFIX2),
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
super(providerId);
}
/**
* Generates an {@link AuthCredential} from a {@link UserCredential} after a
* successful SAML flow completes.
*
* @remarks
*
* For example, to get an {@link AuthCredential}, you could write the
* following code:
*
* ```js
* const userCredential = await signInWithPopup(auth, samlProvider);
* const credential = SAMLAuthProvider.credentialFromResult(userCredential);
* ```
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _SAMLAuthProvider.samlCredentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _SAMLAuthProvider.samlCredentialFromTaggedObject(error.customData || {});
}
/**
* Creates an {@link AuthCredential} from a JSON string or a plain object.
* @param json - A plain object or a JSON string
*/
static credentialFromJSON(json) {
const credential = SAMLAuthCredential2.fromJSON(json);
_assert2(
credential,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return credential;
}
static samlCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { pendingToken, providerId } = tokenResponse;
if (!pendingToken || !providerId) {
return null;
}
try {
return SAMLAuthCredential2._create(providerId, pendingToken);
} catch (e) {
return null;
}
}
};
var TwitterAuthProvider2 = class _TwitterAuthProvider extends BaseOAuthProvider2 {
constructor() {
super(
"twitter.com"
/* ProviderId.TWITTER */
);
}
/**
* Creates a credential for Twitter.
*
* @param token - Twitter access token.
* @param secret - Twitter secret.
*/
static credential(token, secret) {
return OAuthCredential2._fromParams({
providerId: _TwitterAuthProvider.PROVIDER_ID,
signInMethod: _TwitterAuthProvider.TWITTER_SIGN_IN_METHOD,
oauthToken: token,
oauthTokenSecret: secret
});
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
*
* @param userCredential - The user credential.
*/
static credentialFromResult(userCredential) {
return _TwitterAuthProvider.credentialFromTaggedObject(userCredential);
}
/**
* Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
* thrown during a sign-in, link, or reauthenticate operation.
*
* @param userCredential - The user credential.
*/
static credentialFromError(error) {
return _TwitterAuthProvider.credentialFromTaggedObject(error.customData || {});
}
static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
if (!tokenResponse) {
return null;
}
const { oauthAccessToken, oauthTokenSecret } = tokenResponse;
if (!oauthAccessToken || !oauthTokenSecret) {
return null;
}
try {
return _TwitterAuthProvider.credential(oauthAccessToken, oauthTokenSecret);
} catch {
return null;
}
}
};
TwitterAuthProvider2.TWITTER_SIGN_IN_METHOD = "twitter.com";
TwitterAuthProvider2.PROVIDER_ID = "twitter.com";
async function signUp2(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signUp", _addTidIfNecessary2(auth2, request));
}
var UserCredentialImpl2 = class _UserCredentialImpl {
constructor(params) {
this.user = params.user;
this.providerId = params.providerId;
this._tokenResponse = params._tokenResponse;
this.operationType = params.operationType;
}
static async _fromIdTokenResponse(auth2, operationType, idTokenResponse, isAnonymous = false) {
const user = await UserImpl2._fromIdTokenResponse(auth2, idTokenResponse, isAnonymous);
const providerId = providerIdForResponse2(idTokenResponse);
const userCred = new _UserCredentialImpl({
user,
providerId,
_tokenResponse: idTokenResponse,
operationType
});
return userCred;
}
static async _forOperation(user, operationType, response) {
await user._updateTokensIfNecessary(
response,
/* reload */
true
);
const providerId = providerIdForResponse2(response);
return new _UserCredentialImpl({
user,
providerId,
_tokenResponse: response,
operationType
});
}
};
function providerIdForResponse2(response) {
if (response.providerId) {
return response.providerId;
}
if ("phoneNumber" in response) {
return "phone";
}
return null;
}
async function signInAnonymously2(auth2) {
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
const authInternal = _castAuth2(auth2);
await authInternal._initializationPromise;
if (authInternal.currentUser?.isAnonymous) {
return new UserCredentialImpl2({
user: authInternal.currentUser,
providerId: null,
operationType: "signIn"
/* OperationType.SIGN_IN */
});
}
const response = await signUp2(authInternal, {
returnSecureToken: true
});
const userCredential = await UserCredentialImpl2._fromIdTokenResponse(authInternal, "signIn", response, true);
await authInternal._updateCurrentUser(userCredential.user);
return userCredential;
}
var MultiFactorError2 = class _MultiFactorError extends util.FirebaseError {
constructor(auth2, error, operationType, user) {
super(error.code, error.message);
this.operationType = operationType;
this.user = user;
Object.setPrototypeOf(this, _MultiFactorError.prototype);
this.customData = {
appName: auth2.name,
tenantId: auth2.tenantId ?? void 0,
_serverResponse: error.customData._serverResponse,
operationType
};
}
static _fromErrorAndOperation(auth2, error, operationType, user) {
return new _MultiFactorError(auth2, error, operationType, user);
}
};
function _processCredentialSavingMfaContextIfNecessary2(auth2, operationType, credential, user) {
const idTokenProvider = operationType === "reauthenticate" ? credential._getReauthenticationResolver(auth2) : credential._getIdTokenResponse(auth2);
return idTokenProvider.catch((error) => {
if (error.code === `auth/${"multi-factor-auth-required"}`) {
throw MultiFactorError2._fromErrorAndOperation(auth2, error, operationType, user);
}
throw error;
});
}
function providerDataAsNames2(providerData) {
return new Set(providerData.map(({ providerId }) => providerId).filter((pid) => !!pid));
}
async function unlink2(user, providerId) {
const userInternal = util.getModularInstance(user);
await _assertLinkedStatus2(true, userInternal, providerId);
const { providerUserInfo } = await deleteLinkedAccounts2(userInternal.auth, {
idToken: await userInternal.getIdToken(),
deleteProvider: [providerId]
});
const providersLeft = providerDataAsNames2(providerUserInfo || []);
userInternal.providerData = userInternal.providerData.filter((pd) => providersLeft.has(pd.providerId));
if (!providersLeft.has(
"phone"
/* ProviderId.PHONE */
)) {
userInternal.phoneNumber = null;
}
await userInternal.auth._persistUserIfCurrent(userInternal);
return userInternal;
}
async function _link2(user, credential, bypassAuthState = false) {
const response = await _logoutIfInvalidated2(user, credential._linkToIdToken(user.auth, await user.getIdToken()), bypassAuthState);
return UserCredentialImpl2._forOperation(user, "link", response);
}
async function _assertLinkedStatus2(expected, user, provider) {
await _reloadWithoutSaving2(user);
const providerIds = providerDataAsNames2(user.providerData);
const code = expected === false ? "provider-already-linked" : "no-such-provider";
_assert2(providerIds.has(provider) === expected, user.auth, code);
}
async function _reauthenticate2(user, credential, bypassAuthState = false) {
const { auth: auth2 } = user;
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
const operationType = "reauthenticate";
try {
const response = await _logoutIfInvalidated2(user, _processCredentialSavingMfaContextIfNecessary2(auth2, operationType, credential, user), bypassAuthState);
_assert2(
response.idToken,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const parsed = _parseToken2(response.idToken);
_assert2(
parsed,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const { sub: localId } = parsed;
_assert2(
user.uid === localId,
auth2,
"user-mismatch"
/* AuthErrorCode.USER_MISMATCH */
);
return UserCredentialImpl2._forOperation(user, operationType, response);
} catch (e) {
if (e?.code === `auth/${"user-not-found"}`) {
_fail2(
auth2,
"user-mismatch"
/* AuthErrorCode.USER_MISMATCH */
);
}
throw e;
}
}
async function _signInWithCredential2(auth2, credential, bypassAuthState = false) {
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
const operationType = "signIn";
const response = await _processCredentialSavingMfaContextIfNecessary2(auth2, operationType, credential);
const userCredential = await UserCredentialImpl2._fromIdTokenResponse(auth2, operationType, response);
if (!bypassAuthState) {
await auth2._updateCurrentUser(userCredential.user);
}
return userCredential;
}
async function signInWithCredential2(auth2, credential) {
return _signInWithCredential2(_castAuth2(auth2), credential);
}
async function linkWithCredential2(user, credential) {
const userInternal = util.getModularInstance(user);
await _assertLinkedStatus2(false, userInternal, credential.providerId);
return _link2(userInternal, credential);
}
async function reauthenticateWithCredential2(user, credential) {
return _reauthenticate2(util.getModularInstance(user), credential);
}
async function signInWithCustomToken$12(auth2, request) {
return _performSignInRequest2(auth2, "POST", "/v1/accounts:signInWithCustomToken", _addTidIfNecessary2(auth2, request));
}
async function signInWithCustomToken2(auth2, customToken) {
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
const authInternal = _castAuth2(auth2);
const response = await signInWithCustomToken$12(authInternal, {
token: customToken,
returnSecureToken: true
});
const cred = await UserCredentialImpl2._fromIdTokenResponse(authInternal, "signIn", response);
await authInternal._updateCurrentUser(cred.user);
return cred;
}
var MultiFactorInfoImpl2 = class {
constructor(factorId, response) {
this.factorId = factorId;
this.uid = response.mfaEnrollmentId;
this.enrollmentTime = new Date(response.enrolledAt).toUTCString();
this.displayName = response.displayName;
}
static _fromServerResponse(auth2, enrollment) {
if ("phoneInfo" in enrollment) {
return PhoneMultiFactorInfoImpl2._fromServerResponse(auth2, enrollment);
} else if ("totpInfo" in enrollment) {
return TotpMultiFactorInfoImpl2._fromServerResponse(auth2, enrollment);
}
return _fail2(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
};
var PhoneMultiFactorInfoImpl2 = class _PhoneMultiFactorInfoImpl extends MultiFactorInfoImpl2 {
constructor(response) {
super("phone", response);
this.phoneNumber = response.phoneInfo;
}
static _fromServerResponse(_auth, enrollment) {
return new _PhoneMultiFactorInfoImpl(enrollment);
}
};
var TotpMultiFactorInfoImpl2 = class _TotpMultiFactorInfoImpl extends MultiFactorInfoImpl2 {
constructor(response) {
super("totp", response);
}
static _fromServerResponse(_auth, enrollment) {
return new _TotpMultiFactorInfoImpl(enrollment);
}
};
function _setActionCodeSettingsOnRequest2(auth2, request, actionCodeSettings) {
_assert2(
actionCodeSettings.url?.length > 0,
auth2,
"invalid-continue-uri"
/* AuthErrorCode.INVALID_CONTINUE_URI */
);
_assert2(
typeof actionCodeSettings.dynamicLinkDomain === "undefined" || actionCodeSettings.dynamicLinkDomain.length > 0,
auth2,
"invalid-dynamic-link-domain"
/* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */
);
_assert2(
typeof actionCodeSettings.linkDomain === "undefined" || actionCodeSettings.linkDomain.length > 0,
auth2,
"invalid-hosting-link-domain"
/* AuthErrorCode.INVALID_HOSTING_LINK_DOMAIN */
);
request.continueUrl = actionCodeSettings.url;
request.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
request.linkDomain = actionCodeSettings.linkDomain;
request.canHandleCodeInApp = actionCodeSettings.handleCodeInApp;
if (actionCodeSettings.iOS) {
_assert2(
actionCodeSettings.iOS.bundleId.length > 0,
auth2,
"missing-ios-bundle-id"
/* AuthErrorCode.MISSING_IOS_BUNDLE_ID */
);
request.iOSBundleId = actionCodeSettings.iOS.bundleId;
}
if (actionCodeSettings.android) {
_assert2(
actionCodeSettings.android.packageName.length > 0,
auth2,
"missing-android-pkg-name"
/* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */
);
request.androidInstallApp = actionCodeSettings.android.installApp;
request.androidMinimumVersionCode = actionCodeSettings.android.minimumVersion;
request.androidPackageName = actionCodeSettings.android.packageName;
}
}
async function recachePasswordPolicy2(auth2) {
const authInternal = _castAuth2(auth2);
if (authInternal._getPasswordPolicyInternal()) {
await authInternal._updatePasswordPolicy();
}
}
async function sendPasswordResetEmail2(auth2, email, actionCodeSettings) {
const authInternal = _castAuth2(auth2);
const request = {
requestType: "PASSWORD_RESET",
email,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
if (actionCodeSettings) {
_setActionCodeSettingsOnRequest2(authInternal, request, actionCodeSettings);
}
await handleRecaptchaFlow2(
authInternal,
request,
"getOobCode",
sendPasswordResetEmail$12,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
}
async function confirmPasswordReset2(auth2, oobCode, newPassword) {
await resetPassword2(util.getModularInstance(auth2), {
oobCode,
newPassword
}).catch(async (error) => {
if (error.code === `auth/${"password-does-not-meet-requirements"}`) {
void recachePasswordPolicy2(auth2);
}
throw error;
});
}
async function applyActionCode2(auth2, oobCode) {
await applyActionCode$12(util.getModularInstance(auth2), { oobCode });
}
async function checkActionCode2(auth2, oobCode) {
const authModular = util.getModularInstance(auth2);
const response = await resetPassword2(authModular, { oobCode });
const operation = response.requestType;
_assert2(
operation,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
switch (operation) {
case "EMAIL_SIGNIN":
break;
case "VERIFY_AND_CHANGE_EMAIL":
_assert2(
response.newEmail,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
break;
case "REVERT_SECOND_FACTOR_ADDITION":
_assert2(
response.mfaInfo,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
// fall through
default:
_assert2(
response.email,
authModular,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
let multiFactorInfo = null;
if (response.mfaInfo) {
multiFactorInfo = MultiFactorInfoImpl2._fromServerResponse(_castAuth2(authModular), response.mfaInfo);
}
return {
data: {
email: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" ? response.newEmail : response.email) || null,
previousEmail: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" ? response.email : response.newEmail) || null,
multiFactorInfo
},
operation
};
}
async function verifyPasswordResetCode2(auth2, code) {
const { data } = await checkActionCode2(util.getModularInstance(auth2), code);
return data.email;
}
async function createUserWithEmailAndPassword2(auth2, email, password) {
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
const authInternal = _castAuth2(auth2);
const request = {
returnSecureToken: true,
email,
password,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
const signUpResponse = handleRecaptchaFlow2(
authInternal,
request,
"signUpPassword",
signUp2,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
const response = await signUpResponse.catch((error) => {
if (error.code === `auth/${"password-does-not-meet-requirements"}`) {
void recachePasswordPolicy2(auth2);
}
throw error;
});
const userCredential = await UserCredentialImpl2._fromIdTokenResponse(authInternal, "signIn", response);
await authInternal._updateCurrentUser(userCredential.user);
return userCredential;
}
function signInWithEmailAndPassword2(auth2, email, password) {
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
return signInWithCredential2(util.getModularInstance(auth2), EmailAuthProvider2.credential(email, password)).catch(async (error) => {
if (error.code === `auth/${"password-does-not-meet-requirements"}`) {
void recachePasswordPolicy2(auth2);
}
throw error;
});
}
async function sendSignInLinkToEmail2(auth2, email, actionCodeSettings) {
const authInternal = _castAuth2(auth2);
const request = {
requestType: "EMAIL_SIGNIN",
email,
clientType: "CLIENT_TYPE_WEB"
/* RecaptchaClientType.WEB */
};
function setActionCodeSettings(request2, actionCodeSettings2) {
_assert2(
actionCodeSettings2.handleCodeInApp,
authInternal,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
if (actionCodeSettings2) {
_setActionCodeSettingsOnRequest2(authInternal, request2, actionCodeSettings2);
}
}
setActionCodeSettings(request, actionCodeSettings);
await handleRecaptchaFlow2(
authInternal,
request,
"getOobCode",
sendSignInLinkToEmail$12,
"EMAIL_PASSWORD_PROVIDER"
/* RecaptchaAuthProvider.EMAIL_PASSWORD_PROVIDER */
);
}
function isSignInWithEmailLink2(auth2, emailLink) {
const actionCodeUrl = ActionCodeURL2.parseLink(emailLink);
return actionCodeUrl?.operation === "EMAIL_SIGNIN";
}
async function signInWithEmailLink2(auth2, email, emailLink) {
if (app2._isFirebaseServerApp(auth2.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(auth2));
}
const authModular = util.getModularInstance(auth2);
const credential = EmailAuthProvider2.credentialWithLink(email, emailLink || _getCurrentUrl2());
_assert2(
credential._tenantId === (authModular.tenantId || null),
authModular,
"tenant-id-mismatch"
/* AuthErrorCode.TENANT_ID_MISMATCH */
);
return signInWithCredential2(authModular, credential);
}
async function createAuthUri2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:createAuthUri", _addTidIfNecessary2(auth2, request));
}
async function fetchSignInMethodsForEmail2(auth2, email) {
const continueUri = _isHttpOrHttps2() ? _getCurrentUrl2() : "http://localhost";
const request = {
identifier: email,
continueUri
};
const { signinMethods } = await createAuthUri2(util.getModularInstance(auth2), request);
return signinMethods || [];
}
async function sendEmailVerification2(user, actionCodeSettings) {
const userInternal = util.getModularInstance(user);
const idToken = await user.getIdToken();
const request = {
requestType: "VERIFY_EMAIL",
idToken
};
if (actionCodeSettings) {
_setActionCodeSettingsOnRequest2(userInternal.auth, request, actionCodeSettings);
}
const { email } = await sendEmailVerification$12(userInternal.auth, request);
if (email !== user.email) {
await user.reload();
}
}
async function verifyBeforeUpdateEmail2(user, newEmail, actionCodeSettings) {
const userInternal = util.getModularInstance(user);
const idToken = await user.getIdToken();
const request = {
requestType: "VERIFY_AND_CHANGE_EMAIL",
idToken,
newEmail
};
if (actionCodeSettings) {
_setActionCodeSettingsOnRequest2(userInternal.auth, request, actionCodeSettings);
}
const { email } = await verifyAndChangeEmail2(userInternal.auth, request);
if (email !== user.email) {
await user.reload();
}
}
async function updateProfile$12(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v1/accounts:update", request);
}
async function updateProfile2(user, { displayName, photoURL: photoUrl }) {
if (displayName === void 0 && photoUrl === void 0) {
return;
}
const userInternal = util.getModularInstance(user);
const idToken = await userInternal.getIdToken();
const profileRequest = {
idToken,
displayName,
photoUrl,
returnSecureToken: true
};
const response = await _logoutIfInvalidated2(userInternal, updateProfile$12(userInternal.auth, profileRequest));
userInternal.displayName = response.displayName || null;
userInternal.photoURL = response.photoUrl || null;
const passwordProvider = userInternal.providerData.find(
({ providerId }) => providerId === "password"
/* ProviderId.PASSWORD */
);
if (passwordProvider) {
passwordProvider.displayName = userInternal.displayName;
passwordProvider.photoURL = userInternal.photoURL;
}
await userInternal._updateTokensIfNecessary(response);
}
function updateEmail2(user, newEmail) {
const userInternal = util.getModularInstance(user);
if (app2._isFirebaseServerApp(userInternal.auth.app)) {
return Promise.reject(_serverAppCurrentUserOperationNotSupportedError2(userInternal.auth));
}
return updateEmailOrPassword2(userInternal, newEmail, null);
}
function updatePassword2(user, newPassword) {
return updateEmailOrPassword2(util.getModularInstance(user), null, newPassword);
}
async function updateEmailOrPassword2(user, email, password) {
const { auth: auth2 } = user;
const idToken = await user.getIdToken();
const request = {
idToken,
returnSecureToken: true
};
if (email) {
request.email = email;
}
if (password) {
request.password = password;
}
const response = await _logoutIfInvalidated2(user, updateEmailPassword2(auth2, request));
await user._updateTokensIfNecessary(
response,
/* reload */
true
);
}
function _fromIdTokenResponse2(idTokenResponse) {
if (!idTokenResponse) {
return null;
}
const { providerId } = idTokenResponse;
const profile = idTokenResponse.rawUserInfo ? JSON.parse(idTokenResponse.rawUserInfo) : {};
const isNewUser = idTokenResponse.isNewUser || idTokenResponse.kind === "identitytoolkit#SignupNewUserResponse";
if (!providerId && idTokenResponse?.idToken) {
const signInProvider = _parseToken2(idTokenResponse.idToken)?.firebase?.["sign_in_provider"];
if (signInProvider) {
const filteredProviderId = signInProvider !== "anonymous" && signInProvider !== "custom" ? signInProvider : null;
return new GenericAdditionalUserInfo2(isNewUser, filteredProviderId);
}
}
if (!providerId) {
return null;
}
switch (providerId) {
case "facebook.com":
return new FacebookAdditionalUserInfo2(isNewUser, profile);
case "github.com":
return new GithubAdditionalUserInfo2(isNewUser, profile);
case "google.com":
return new GoogleAdditionalUserInfo2(isNewUser, profile);
case "twitter.com":
return new TwitterAdditionalUserInfo2(isNewUser, profile, idTokenResponse.screenName || null);
case "custom":
case "anonymous":
return new GenericAdditionalUserInfo2(isNewUser, null);
default:
return new GenericAdditionalUserInfo2(isNewUser, providerId, profile);
}
}
var GenericAdditionalUserInfo2 = class {
constructor(isNewUser, providerId, profile = {}) {
this.isNewUser = isNewUser;
this.providerId = providerId;
this.profile = profile;
}
};
var FederatedAdditionalUserInfoWithUsername2 = class extends GenericAdditionalUserInfo2 {
constructor(isNewUser, providerId, profile, username) {
super(isNewUser, providerId, profile);
this.username = username;
}
};
var FacebookAdditionalUserInfo2 = class extends GenericAdditionalUserInfo2 {
constructor(isNewUser, profile) {
super(isNewUser, "facebook.com", profile);
}
};
var GithubAdditionalUserInfo2 = class extends FederatedAdditionalUserInfoWithUsername2 {
constructor(isNewUser, profile) {
super(isNewUser, "github.com", profile, typeof profile?.login === "string" ? profile?.login : null);
}
};
var GoogleAdditionalUserInfo2 = class extends GenericAdditionalUserInfo2 {
constructor(isNewUser, profile) {
super(isNewUser, "google.com", profile);
}
};
var TwitterAdditionalUserInfo2 = class extends FederatedAdditionalUserInfoWithUsername2 {
constructor(isNewUser, profile, screenName) {
super(isNewUser, "twitter.com", profile, screenName);
}
};
function getAdditionalUserInfo2(userCredential) {
const { user, _tokenResponse } = userCredential;
if (user.isAnonymous && !_tokenResponse) {
return {
providerId: null,
isNewUser: false,
profile: null
};
}
return _fromIdTokenResponse2(_tokenResponse);
}
function setPersistence2(auth2, persistence) {
return util.getModularInstance(auth2).setPersistence(persistence);
}
function initializeRecaptchaConfig2(auth2) {
return _initializeRecaptchaConfig2(auth2);
}
async function validatePassword2(auth2, password) {
const authInternal = _castAuth2(auth2);
return authInternal.validatePassword(password);
}
function onIdTokenChanged2(auth2, nextOrObserver, error, completed) {
return util.getModularInstance(auth2).onIdTokenChanged(nextOrObserver, error, completed);
}
function beforeAuthStateChanged2(auth2, callback, onAbort) {
return util.getModularInstance(auth2).beforeAuthStateChanged(callback, onAbort);
}
function onAuthStateChanged2(auth2, nextOrObserver, error, completed) {
return util.getModularInstance(auth2).onAuthStateChanged(nextOrObserver, error, completed);
}
function useDeviceLanguage2(auth2) {
util.getModularInstance(auth2).useDeviceLanguage();
}
function updateCurrentUser2(auth2, user) {
return util.getModularInstance(auth2).updateCurrentUser(user);
}
function signOut2(auth2) {
return util.getModularInstance(auth2).signOut();
}
function revokeAccessToken2(auth2, token) {
const authInternal = _castAuth2(auth2);
return authInternal.revokeAccessToken(token);
}
async function deleteUser2(user) {
return util.getModularInstance(user).delete();
}
var MultiFactorSessionImpl2 = class _MultiFactorSessionImpl {
constructor(type, credential, user) {
this.type = type;
this.credential = credential;
this.user = user;
}
static _fromIdtoken(idToken, user) {
return new _MultiFactorSessionImpl("enroll", idToken, user);
}
static _fromMfaPendingCredential(mfaPendingCredential) {
return new _MultiFactorSessionImpl("signin", mfaPendingCredential);
}
toJSON() {
const key = this.type === "enroll" ? "idToken" : "pendingCredential";
return {
multiFactorSession: {
[key]: this.credential
}
};
}
static fromJSON(obj) {
if (obj?.multiFactorSession) {
if (obj.multiFactorSession?.pendingCredential) {
return _MultiFactorSessionImpl._fromMfaPendingCredential(obj.multiFactorSession.pendingCredential);
} else if (obj.multiFactorSession?.idToken) {
return _MultiFactorSessionImpl._fromIdtoken(obj.multiFactorSession.idToken);
}
}
return null;
}
};
var MultiFactorResolverImpl2 = class _MultiFactorResolverImpl {
constructor(session, hints, signInResolver) {
this.session = session;
this.hints = hints;
this.signInResolver = signInResolver;
}
/** @internal */
static _fromError(authExtern, error) {
const auth2 = _castAuth2(authExtern);
const serverResponse = error.customData._serverResponse;
const hints = (serverResponse.mfaInfo || []).map((enrollment) => MultiFactorInfoImpl2._fromServerResponse(auth2, enrollment));
_assert2(
serverResponse.mfaPendingCredential,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const session = MultiFactorSessionImpl2._fromMfaPendingCredential(serverResponse.mfaPendingCredential);
return new _MultiFactorResolverImpl(session, hints, async (assertion) => {
const mfaResponse = await assertion._process(auth2, session);
delete serverResponse.mfaInfo;
delete serverResponse.mfaPendingCredential;
const idTokenResponse = {
...serverResponse,
idToken: mfaResponse.idToken,
refreshToken: mfaResponse.refreshToken
};
switch (error.operationType) {
case "signIn":
const userCredential = await UserCredentialImpl2._fromIdTokenResponse(auth2, error.operationType, idTokenResponse);
await auth2._updateCurrentUser(userCredential.user);
return userCredential;
case "reauthenticate":
_assert2(
error.user,
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
return UserCredentialImpl2._forOperation(error.user, error.operationType, idTokenResponse);
default:
_fail2(
auth2,
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
}
});
}
async resolveSignIn(assertionExtern) {
const assertion = assertionExtern;
return this.signInResolver(assertion);
}
};
function getMultiFactorResolver2(auth2, error) {
const authModular = util.getModularInstance(auth2);
const errorInternal = error;
_assert2(
error.customData.operationType,
authModular,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
_assert2(
errorInternal.customData._serverResponse?.mfaPendingCredential,
authModular,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return MultiFactorResolverImpl2._fromError(authModular, errorInternal);
}
function startEnrollTotpMfa2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v2/accounts/mfaEnrollment:start", _addTidIfNecessary2(auth2, request));
}
function finalizeEnrollTotpMfa2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v2/accounts/mfaEnrollment:finalize", _addTidIfNecessary2(auth2, request));
}
function withdrawMfa2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v2/accounts/mfaEnrollment:withdraw", _addTidIfNecessary2(auth2, request));
}
var MultiFactorUserImpl2 = class _MultiFactorUserImpl {
constructor(user) {
this.user = user;
this.enrolledFactors = [];
user._onReload((userInfo) => {
if (userInfo.mfaInfo) {
this.enrolledFactors = userInfo.mfaInfo.map((enrollment) => MultiFactorInfoImpl2._fromServerResponse(user.auth, enrollment));
}
});
}
static _fromUser(user) {
return new _MultiFactorUserImpl(user);
}
async getSession() {
return MultiFactorSessionImpl2._fromIdtoken(await this.user.getIdToken(), this.user);
}
async enroll(assertionExtern, displayName) {
const assertion = assertionExtern;
const session = await this.getSession();
const finalizeMfaResponse = await _logoutIfInvalidated2(this.user, assertion._process(this.user.auth, session, displayName));
await this.user._updateTokensIfNecessary(finalizeMfaResponse);
return this.user.reload();
}
async unenroll(infoOrUid) {
const mfaEnrollmentId = typeof infoOrUid === "string" ? infoOrUid : infoOrUid.uid;
const idToken = await this.user.getIdToken();
try {
const idTokenResponse = await _logoutIfInvalidated2(this.user, withdrawMfa2(this.user.auth, {
idToken,
mfaEnrollmentId
}));
this.enrolledFactors = this.enrolledFactors.filter(({ uid }) => uid !== mfaEnrollmentId);
await this.user._updateTokensIfNecessary(idTokenResponse);
await this.user.reload();
} catch (e) {
throw e;
}
}
};
var multiFactorUserCache2 = /* @__PURE__ */ new WeakMap();
function multiFactor2(user) {
const userModular = util.getModularInstance(user);
if (!multiFactorUserCache2.has(userModular)) {
multiFactorUserCache2.set(userModular, MultiFactorUserImpl2._fromUser(userModular));
}
return multiFactorUserCache2.get(userModular);
}
var name6 = "@firebase/auth";
var version6 = "1.11.1";
var AuthInterop2 = class {
constructor(auth2) {
this.auth = auth2;
this.internalListeners = /* @__PURE__ */ new Map();
}
getUid() {
this.assertAuthConfigured();
return this.auth.currentUser?.uid || null;
}
async getToken(forceRefresh) {
this.assertAuthConfigured();
await this.auth._initializationPromise;
if (!this.auth.currentUser) {
return null;
}
const accessToken = await this.auth.currentUser.getIdToken(forceRefresh);
return { accessToken };
}
addAuthTokenListener(listener) {
this.assertAuthConfigured();
if (this.internalListeners.has(listener)) {
return;
}
const unsubscribe = this.auth.onIdTokenChanged((user) => {
listener(user?.stsTokenManager.accessToken || null);
});
this.internalListeners.set(listener, unsubscribe);
this.updateProactiveRefresh();
}
removeAuthTokenListener(listener) {
this.assertAuthConfigured();
const unsubscribe = this.internalListeners.get(listener);
if (!unsubscribe) {
return;
}
this.internalListeners.delete(listener);
unsubscribe();
this.updateProactiveRefresh();
}
assertAuthConfigured() {
_assert2(
this.auth._initializationPromise,
"dependent-sdk-initialized-before-auth"
/* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */
);
}
updateProactiveRefresh() {
if (this.internalListeners.size > 0) {
this.auth._startProactiveRefresh();
} else {
this.auth._stopProactiveRefresh();
}
}
};
function getVersionForPlatform2(clientPlatform) {
switch (clientPlatform) {
case "Node":
return "node";
case "ReactNative":
return "rn";
case "Worker":
return "webworker";
case "Cordova":
return "cordova";
case "WebExtension":
return "web-extension";
default:
return void 0;
}
}
function registerAuth2(clientPlatform) {
app2._registerComponent(new component.Component(
"auth",
(container, { options: deps }) => {
const app3 = container.getProvider("app").getImmediate();
const heartbeatServiceProvider = container.getProvider("heartbeat");
const appCheckServiceProvider = container.getProvider("app-check-internal");
const { apiKey, authDomain } = app3.options;
_assert2(apiKey && !apiKey.includes(":"), "invalid-api-key", { appName: app3.name });
const config = {
apiKey,
authDomain,
clientPlatform,
apiHost: "identitytoolkit.googleapis.com",
tokenApiHost: "securetoken.googleapis.com",
apiScheme: "https",
sdkClientVersion: _getClientVersion2(clientPlatform)
};
const authInstance = new AuthImpl2(app3, heartbeatServiceProvider, appCheckServiceProvider, config);
_initializeAuthInstance2(authInstance, deps);
return authInstance;
},
"PUBLIC"
/* ComponentType.PUBLIC */
).setInstantiationMode(
"EXPLICIT"
/* InstantiationMode.EXPLICIT */
).setInstanceCreatedCallback((container, _instanceIdentifier, _instance) => {
const authInternalProvider = container.getProvider(
"auth-internal"
/* _ComponentName.AUTH_INTERNAL */
);
authInternalProvider.initialize();
}));
app2._registerComponent(new component.Component(
"auth-internal",
(container) => {
const auth2 = _castAuth2(container.getProvider(
"auth"
/* _ComponentName.AUTH */
).getImmediate());
return ((auth3) => new AuthInterop2(auth3))(auth2);
},
"PRIVATE"
/* ComponentType.PRIVATE */
).setInstantiationMode(
"EXPLICIT"
/* InstantiationMode.EXPLICIT */
));
app2.registerVersion(name6, version6, getVersionForPlatform2(clientPlatform));
app2.registerVersion(name6, version6, "cjs2020");
}
FetchProvider2.initialize(fetch, Headers, Response);
function getAuth2(app$1 = app2.getApp()) {
const provider = app2._getProvider(app$1, "auth");
if (provider.isInitialized()) {
return provider.getImmediate();
}
const auth2 = initializeAuth2(app$1);
const authEmulatorHost = util.getDefaultEmulatorHost("auth");
if (authEmulatorHost) {
connectAuthEmulator2(auth2, `http://${authEmulatorHost}`);
}
return auth2;
}
registerAuth2(
"Node"
/* ClientPlatform.NODE */
);
var NOT_AVAILABLE_ERROR2 = _createError2(
"operation-not-supported-in-this-environment"
/* AuthErrorCode.OPERATION_NOT_SUPPORTED */
);
async function fail2() {
throw NOT_AVAILABLE_ERROR2;
}
var FailClass2 = class {
constructor() {
throw NOT_AVAILABLE_ERROR2;
}
};
var browserLocalPersistence2 = inMemoryPersistence2;
var browserSessionPersistence2 = inMemoryPersistence2;
var browserCookiePersistence2 = inMemoryPersistence2;
var indexedDBLocalPersistence2 = inMemoryPersistence2;
var browserPopupRedirectResolver2 = NOT_AVAILABLE_ERROR2;
var PhoneAuthProvider2 = FailClass2;
var signInWithPhoneNumber2 = fail2;
var linkWithPhoneNumber2 = fail2;
var reauthenticateWithPhoneNumber2 = fail2;
var updatePhoneNumber2 = fail2;
var signInWithPopup2 = fail2;
var linkWithPopup2 = fail2;
var reauthenticateWithPopup2 = fail2;
var signInWithRedirect2 = fail2;
var linkWithRedirect2 = fail2;
var reauthenticateWithRedirect2 = fail2;
var getRedirectResult2 = fail2;
var RecaptchaVerifier2 = FailClass2;
var PhoneMultiFactorGenerator2 = class {
static assertion() {
throw NOT_AVAILABLE_ERROR2;
}
};
AuthImpl2.prototype.setPersistence = async () => {
};
function finalizeSignInTotpMfa2(auth2, request) {
return _performApiRequest2(auth2, "POST", "/v2/accounts/mfaSignIn:finalize", _addTidIfNecessary2(auth2, request));
}
var MultiFactorAssertionImpl2 = class {
constructor(factorId) {
this.factorId = factorId;
}
_process(auth2, session, displayName) {
switch (session.type) {
case "enroll":
return this._finalizeEnroll(auth2, session.credential, displayName);
case "signin":
return this._finalizeSignIn(auth2, session.credential);
default:
return debugFail2("unexpected MultiFactorSessionType");
}
}
};
var TotpMultiFactorGenerator2 = class {
/**
* Provides a {@link TotpMultiFactorAssertion} to confirm ownership of
* the TOTP (time-based one-time password) second factor.
* This assertion is used to complete enrollment in TOTP second factor.
*
* @param secret A {@link TotpSecret} containing the shared secret key and other TOTP parameters.
* @param oneTimePassword One-time password from TOTP App.
* @returns A {@link TotpMultiFactorAssertion} which can be used with
* {@link MultiFactorUser.enroll}.
*/
static assertionForEnrollment(secret, oneTimePassword) {
return TotpMultiFactorAssertionImpl2._fromSecret(secret, oneTimePassword);
}
/**
* Provides a {@link TotpMultiFactorAssertion} to confirm ownership of the TOTP second factor.
* This assertion is used to complete signIn with TOTP as the second factor.
*
* @param enrollmentId identifies the enrolled TOTP second factor.
* @param oneTimePassword One-time password from TOTP App.
* @returns A {@link TotpMultiFactorAssertion} which can be used with
* {@link MultiFactorResolver.resolveSignIn}.
*/
static assertionForSignIn(enrollmentId, oneTimePassword) {
return TotpMultiFactorAssertionImpl2._fromEnrollmentId(enrollmentId, oneTimePassword);
}
/**
* Returns a promise to {@link TotpSecret} which contains the TOTP shared secret key and other parameters.
* Creates a TOTP secret as part of enrolling a TOTP second factor.
* Used for generating a QR code URL or inputting into a TOTP app.
* This method uses the auth instance corresponding to the user in the multiFactorSession.
*
* @param session The {@link MultiFactorSession} that the user is part of.
* @returns A promise to {@link TotpSecret}.
*/
static async generateSecret(session) {
const mfaSession = session;
_assert2(
typeof mfaSession.user?.auth !== "undefined",
"internal-error"
/* AuthErrorCode.INTERNAL_ERROR */
);
const response = await startEnrollTotpMfa2(mfaSession.user.auth, {
idToken: mfaSession.credential,
totpEnrollmentInfo: {}
});
return TotpSecret2._fromStartTotpMfaEnrollmentResponse(response, mfaSession.user.auth);
}
};
TotpMultiFactorGenerator2.FACTOR_ID = "totp";
var TotpMultiFactorAssertionImpl2 = class _TotpMultiFactorAssertionImpl extends MultiFactorAssertionImpl2 {
constructor(otp, enrollmentId, secret) {
super(
"totp"
/* FactorId.TOTP */
);
this.otp = otp;
this.enrollmentId = enrollmentId;
this.secret = secret;
}
/** @internal */
static _fromSecret(secret, otp) {
return new _TotpMultiFactorAssertionImpl(otp, void 0, secret);
}
/** @internal */
static _fromEnrollmentId(enrollmentId, otp) {
return new _TotpMultiFactorAssertionImpl(otp, enrollmentId);
}
/** @internal */
async _finalizeEnroll(auth2, idToken, displayName) {
_assert2(
typeof this.secret !== "undefined",
auth2,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
return finalizeEnrollTotpMfa2(auth2, {
idToken,
displayName,
totpVerificationInfo: this.secret._makeTotpVerificationInfo(this.otp)
});
}
/** @internal */
async _finalizeSignIn(auth2, mfaPendingCredential) {
_assert2(
this.enrollmentId !== void 0 && this.otp !== void 0,
auth2,
"argument-error"
/* AuthErrorCode.ARGUMENT_ERROR */
);
const totpVerificationInfo = { verificationCode: this.otp };
return finalizeSignInTotpMfa2(auth2, {
mfaPendingCredential,
mfaEnrollmentId: this.enrollmentId,
totpVerificationInfo
});
}
};
var TotpSecret2 = class _TotpSecret {
// The public members are declared outside the constructor so the docs can be generated.
constructor(secretKey, hashingAlgorithm, codeLength, codeIntervalSeconds, enrollmentCompletionDeadline, sessionInfo, auth2) {
this.sessionInfo = sessionInfo;
this.auth = auth2;
this.secretKey = secretKey;
this.hashingAlgorithm = hashingAlgorithm;
this.codeLength = codeLength;
this.codeIntervalSeconds = codeIntervalSeconds;
this.enrollmentCompletionDeadline = enrollmentCompletionDeadline;
}
/** @internal */
static _fromStartTotpMfaEnrollmentResponse(response, auth2) {
return new _TotpSecret(response.totpSessionInfo.sharedSecretKey, response.totpSessionInfo.hashingAlgorithm, response.totpSessionInfo.verificationCodeLength, response.totpSessionInfo.periodSec, new Date(response.totpSessionInfo.finalizeEnrollmentTime).toUTCString(), response.totpSessionInfo.sessionInfo, auth2);
}
/** @internal */
_makeTotpVerificationInfo(otp) {
return { sessionInfo: this.sessionInfo, verificationCode: otp };
}
/**
* Returns a QR code URL as described in
* https://github.com/google/google-authenticator/wiki/Key-Uri-Format
* This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator.
* If the optional parameters are unspecified, an accountName of <userEmail> and issuer of <firebaseAppName> are used.
*
* @param accountName the name of the account/app along with a user identifier.
* @param issuer issuer of the TOTP (likely the app name).
* @returns A QR code URL string.
*/
generateQrCodeUrl(accountName, issuer) {
let useDefaults = false;
if (_isEmptyString2(accountName) || _isEmptyString2(issuer)) {
useDefaults = true;
}
if (useDefaults) {
if (_isEmptyString2(accountName)) {
accountName = this.auth.currentUser?.email || "unknownuser";
}
if (_isEmptyString2(issuer)) {
issuer = this.auth.name;
}
}
return `otpauth://totp/${issuer}:${accountName}?secret=${this.secretKey}&issuer=${issuer}&algorithm=${this.hashingAlgorithm}&digits=${this.codeLength}`;
}
};
function _isEmptyString2(input) {
return typeof input === "undefined" || input?.length === 0;
}
exports2.AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY2;
exports2.ActionCodeOperation = ActionCodeOperation2;
exports2.ActionCodeURL = ActionCodeURL2;
exports2.AuthCredential = AuthCredential2;
exports2.AuthImpl = AuthImpl2;
exports2.BaseOAuthProvider = BaseOAuthProvider2;
exports2.EmailAuthCredential = EmailAuthCredential2;
exports2.EmailAuthProvider = EmailAuthProvider2;
exports2.FacebookAuthProvider = FacebookAuthProvider2;
exports2.FactorId = FactorId2;
exports2.FederatedAuthProvider = FederatedAuthProvider2;
exports2.FetchProvider = FetchProvider2;
exports2.GithubAuthProvider = GithubAuthProvider2;
exports2.GoogleAuthProvider = GoogleAuthProvider2;
exports2.OAuthCredential = OAuthCredential2;
exports2.OAuthProvider = OAuthProvider2;
exports2.OperationType = OperationType2;
exports2.PhoneAuthCredential = PhoneAuthCredential2;
exports2.PhoneAuthProvider = PhoneAuthProvider2;
exports2.PhoneMultiFactorGenerator = PhoneMultiFactorGenerator2;
exports2.ProviderId = ProviderId2;
exports2.RecaptchaVerifier = RecaptchaVerifier2;
exports2.SAMLAuthCredential = SAMLAuthCredential2;
exports2.SAMLAuthProvider = SAMLAuthProvider2;
exports2.SignInMethod = SignInMethod2;
exports2.TotpMultiFactorGenerator = TotpMultiFactorGenerator2;
exports2.TotpSecret = TotpSecret2;
exports2.TwitterAuthProvider = TwitterAuthProvider2;
exports2.UserImpl = UserImpl2;
exports2._assert = _assert2;
exports2._castAuth = _castAuth2;
exports2._createError = _createError2;
exports2._emulatorUrl = _emulatorUrl2;
exports2._fail = _fail2;
exports2._getClientVersion = _getClientVersion2;
exports2._getInstance = _getInstance2;
exports2._isAndroid = _isAndroid2;
exports2._isIE10 = _isIE10;
exports2._isIOS = _isIOS;
exports2._isIOS7Or8 = _isIOS7Or8;
exports2._isMobileBrowser = _isMobileBrowser;
exports2._link = _link2;
exports2._performApiRequest = _performApiRequest2;
exports2._persistenceKeyName = _persistenceKeyName2;
exports2._reauthenticate = _reauthenticate2;
exports2._serverAppCurrentUserOperationNotSupportedError = _serverAppCurrentUserOperationNotSupportedError2;
exports2._signInWithCredential = _signInWithCredential2;
exports2.applyActionCode = applyActionCode2;
exports2.beforeAuthStateChanged = beforeAuthStateChanged2;
exports2.browserCookiePersistence = browserCookiePersistence2;
exports2.browserLocalPersistence = browserLocalPersistence2;
exports2.browserPopupRedirectResolver = browserPopupRedirectResolver2;
exports2.browserSessionPersistence = browserSessionPersistence2;
exports2.checkActionCode = checkActionCode2;
exports2.confirmPasswordReset = confirmPasswordReset2;
exports2.connectAuthEmulator = connectAuthEmulator2;
exports2.createUserWithEmailAndPassword = createUserWithEmailAndPassword2;
exports2.debugAssert = debugAssert2;
exports2.debugErrorMap = debugErrorMap2;
exports2.deleteUser = deleteUser2;
exports2.fetchSignInMethodsForEmail = fetchSignInMethodsForEmail2;
exports2.getAdditionalUserInfo = getAdditionalUserInfo2;
exports2.getAuth = getAuth2;
exports2.getIdToken = getIdToken2;
exports2.getIdTokenResult = getIdTokenResult2;
exports2.getMultiFactorResolver = getMultiFactorResolver2;
exports2.getRedirectResult = getRedirectResult2;
exports2.inMemoryPersistence = inMemoryPersistence2;
exports2.indexedDBLocalPersistence = indexedDBLocalPersistence2;
exports2.initializeAuth = initializeAuth2;
exports2.initializeRecaptchaConfig = initializeRecaptchaConfig2;
exports2.isSignInWithEmailLink = isSignInWithEmailLink2;
exports2.linkWithCredential = linkWithCredential2;
exports2.linkWithPhoneNumber = linkWithPhoneNumber2;
exports2.linkWithPopup = linkWithPopup2;
exports2.linkWithRedirect = linkWithRedirect2;
exports2.multiFactor = multiFactor2;
exports2.onAuthStateChanged = onAuthStateChanged2;
exports2.onIdTokenChanged = onIdTokenChanged2;
exports2.parseActionCodeURL = parseActionCodeURL2;
exports2.prodErrorMap = prodErrorMap2;
exports2.reauthenticateWithCredential = reauthenticateWithCredential2;
exports2.reauthenticateWithPhoneNumber = reauthenticateWithPhoneNumber2;
exports2.reauthenticateWithPopup = reauthenticateWithPopup2;
exports2.reauthenticateWithRedirect = reauthenticateWithRedirect2;
exports2.reload = reload2;
exports2.revokeAccessToken = revokeAccessToken2;
exports2.sendEmailVerification = sendEmailVerification2;
exports2.sendPasswordResetEmail = sendPasswordResetEmail2;
exports2.sendSignInLinkToEmail = sendSignInLinkToEmail2;
exports2.setPersistence = setPersistence2;
exports2.signInAnonymously = signInAnonymously2;
exports2.signInWithCredential = signInWithCredential2;
exports2.signInWithCustomToken = signInWithCustomToken2;
exports2.signInWithEmailAndPassword = signInWithEmailAndPassword2;
exports2.signInWithEmailLink = signInWithEmailLink2;
exports2.signInWithIdp = signInWithIdp2;
exports2.signInWithPhoneNumber = signInWithPhoneNumber2;
exports2.signInWithPopup = signInWithPopup2;
exports2.signInWithRedirect = signInWithRedirect2;
exports2.signOut = signOut2;
exports2.unlink = unlink2;
exports2.updateCurrentUser = updateCurrentUser2;
exports2.updateEmail = updateEmail2;
exports2.updatePassword = updatePassword2;
exports2.updatePhoneNumber = updatePhoneNumber2;
exports2.updateProfile = updateProfile2;
exports2.useDeviceLanguage = useDeviceLanguage2;
exports2.validatePassword = validatePassword2;
exports2.verifyBeforeUpdateEmail = verifyBeforeUpdateEmail2;
exports2.verifyPasswordResetCode = verifyPasswordResetCode2;
}
});
// node_modules/@firebase/auth/dist/node/index.js
var require_node = __commonJS({
"node_modules/@firebase/auth/dist/node/index.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var totp = require_totp_50d5d5dd();
require_index_cjs3();
require_index_node_cjs();
require_index_cjs();
require_index_cjs2();
exports2.ActionCodeOperation = totp.ActionCodeOperation;
exports2.ActionCodeURL = totp.ActionCodeURL;
exports2.AuthCredential = totp.AuthCredential;
exports2.AuthErrorCodes = totp.AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY;
exports2.EmailAuthCredential = totp.EmailAuthCredential;
exports2.EmailAuthProvider = totp.EmailAuthProvider;
exports2.FacebookAuthProvider = totp.FacebookAuthProvider;
exports2.FactorId = totp.FactorId;
exports2.GithubAuthProvider = totp.GithubAuthProvider;
exports2.GoogleAuthProvider = totp.GoogleAuthProvider;
exports2.OAuthCredential = totp.OAuthCredential;
exports2.OAuthProvider = totp.OAuthProvider;
exports2.OperationType = totp.OperationType;
exports2.PhoneAuthCredential = totp.PhoneAuthCredential;
exports2.PhoneAuthProvider = totp.PhoneAuthProvider;
exports2.PhoneMultiFactorGenerator = totp.PhoneMultiFactorGenerator;
exports2.ProviderId = totp.ProviderId;
exports2.RecaptchaVerifier = totp.RecaptchaVerifier;
exports2.SAMLAuthProvider = totp.SAMLAuthProvider;
exports2.SignInMethod = totp.SignInMethod;
exports2.TotpMultiFactorGenerator = totp.TotpMultiFactorGenerator;
exports2.TotpSecret = totp.TotpSecret;
exports2.TwitterAuthProvider = totp.TwitterAuthProvider;
exports2.applyActionCode = totp.applyActionCode;
exports2.beforeAuthStateChanged = totp.beforeAuthStateChanged;
exports2.browserCookiePersistence = totp.browserCookiePersistence;
exports2.browserLocalPersistence = totp.browserLocalPersistence;
exports2.browserPopupRedirectResolver = totp.browserPopupRedirectResolver;
exports2.browserSessionPersistence = totp.browserSessionPersistence;
exports2.checkActionCode = totp.checkActionCode;
exports2.confirmPasswordReset = totp.confirmPasswordReset;
exports2.connectAuthEmulator = totp.connectAuthEmulator;
exports2.createUserWithEmailAndPassword = totp.createUserWithEmailAndPassword;
exports2.debugErrorMap = totp.debugErrorMap;
exports2.deleteUser = totp.deleteUser;
exports2.fetchSignInMethodsForEmail = totp.fetchSignInMethodsForEmail;
exports2.getAdditionalUserInfo = totp.getAdditionalUserInfo;
exports2.getAuth = totp.getAuth;
exports2.getIdToken = totp.getIdToken;
exports2.getIdTokenResult = totp.getIdTokenResult;
exports2.getMultiFactorResolver = totp.getMultiFactorResolver;
exports2.getRedirectResult = totp.getRedirectResult;
exports2.inMemoryPersistence = totp.inMemoryPersistence;
exports2.indexedDBLocalPersistence = totp.indexedDBLocalPersistence;
exports2.initializeAuth = totp.initializeAuth;
exports2.initializeRecaptchaConfig = totp.initializeRecaptchaConfig;
exports2.isSignInWithEmailLink = totp.isSignInWithEmailLink;
exports2.linkWithCredential = totp.linkWithCredential;
exports2.linkWithPhoneNumber = totp.linkWithPhoneNumber;
exports2.linkWithPopup = totp.linkWithPopup;
exports2.linkWithRedirect = totp.linkWithRedirect;
exports2.multiFactor = totp.multiFactor;
exports2.onAuthStateChanged = totp.onAuthStateChanged;
exports2.onIdTokenChanged = totp.onIdTokenChanged;
exports2.parseActionCodeURL = totp.parseActionCodeURL;
exports2.prodErrorMap = totp.prodErrorMap;
exports2.reauthenticateWithCredential = totp.reauthenticateWithCredential;
exports2.reauthenticateWithPhoneNumber = totp.reauthenticateWithPhoneNumber;
exports2.reauthenticateWithPopup = totp.reauthenticateWithPopup;
exports2.reauthenticateWithRedirect = totp.reauthenticateWithRedirect;
exports2.reload = totp.reload;
exports2.revokeAccessToken = totp.revokeAccessToken;
exports2.sendEmailVerification = totp.sendEmailVerification;
exports2.sendPasswordResetEmail = totp.sendPasswordResetEmail;
exports2.sendSignInLinkToEmail = totp.sendSignInLinkToEmail;
exports2.setPersistence = totp.setPersistence;
exports2.signInAnonymously = totp.signInAnonymously;
exports2.signInWithCredential = totp.signInWithCredential;
exports2.signInWithCustomToken = totp.signInWithCustomToken;
exports2.signInWithEmailAndPassword = totp.signInWithEmailAndPassword;
exports2.signInWithEmailLink = totp.signInWithEmailLink;
exports2.signInWithPhoneNumber = totp.signInWithPhoneNumber;
exports2.signInWithPopup = totp.signInWithPopup;
exports2.signInWithRedirect = totp.signInWithRedirect;
exports2.signOut = totp.signOut;
exports2.unlink = totp.unlink;
exports2.updateCurrentUser = totp.updateCurrentUser;
exports2.updateEmail = totp.updateEmail;
exports2.updatePassword = totp.updatePassword;
exports2.updatePhoneNumber = totp.updatePhoneNumber;
exports2.updateProfile = totp.updateProfile;
exports2.useDeviceLanguage = totp.useDeviceLanguage;
exports2.validatePassword = totp.validatePassword;
exports2.verifyBeforeUpdateEmail = totp.verifyBeforeUpdateEmail;
exports2.verifyPasswordResetCode = totp.verifyPasswordResetCode;
}
});
// node_modules/firebase/auth/dist/index.cjs.js
var require_index_cjs4 = __commonJS({
"node_modules/firebase/auth/dist/index.cjs.js"(exports2) {
"use strict";
Object.defineProperty(exports2, "__esModule", { value: true });
var auth2 = require_node();
Object.keys(auth2).forEach(function(k) {
if (k !== "default" && !exports2.hasOwnProperty(k)) Object.defineProperty(exports2, k, {
enumerable: true,
get: function() {
return auth2[k];
}
});
});
}
});
// src/main.ts
var main_exports = {};
__export(main_exports, {
default: () => UuuglPlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian4 = require("obsidian");
// src/auth-manager.ts
init_firebase_config();
init_dist2();
var import_obsidian = require("obsidian");
var AuthManager = class {
constructor() {
this.authCallbacks = /* @__PURE__ */ new Map();
this.AUTH_URL = "https://uuu.gl/auth/obsidian";
}
/**
* Sign in with Google OAuth (cross-platform)
* Opens browser for authentication, returns to Obsidian via obsidian:// URL
*/
async signInWithGoogle() {
return new Promise((resolve, reject) => {
const callbackId = `auth-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
console.log("\u{1F510} Starting cross-platform OAuth flow...");
this.authCallbacks.set(callbackId, async (customToken) => {
try {
console.log("\u{1F511} Received custom token, authenticating with Firebase...");
const userCredential = await signInWithCustomToken(auth, customToken);
const user = userCredential.user;
console.log("\u2705 Firebase authentication successful:", user.email);
const authUser = {
uid: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL
};
this.authCallbacks.delete(callbackId);
resolve(authUser);
} catch (error) {
console.error("\u274C Firebase authentication failed:", error);
this.authCallbacks.delete(callbackId);
reject(error);
}
});
const authUrl = `${this.AUTH_URL}?callbackId=${callbackId}`;
console.log("\u{1F517} Opening browser for authentication...");
console.log("Platform:", import_obsidian.Platform.isDesktopApp ? "Desktop" : import_obsidian.Platform.isMobileApp ? "Mobile" : "Unknown");
this.openExternalBrowser(authUrl);
setTimeout(() => {
if (this.authCallbacks.has(callbackId)) {
this.authCallbacks.delete(callbackId);
reject(new Error("Authentication timeout"));
}
}, 5 * 60 * 1e3);
});
}
/**
* Open external browser (cross-platform)
*/
openExternalBrowser(url) {
try {
if (import_obsidian.Platform.isDesktopApp) {
const { shell } = require("electron");
shell.openExternal(url);
console.log("\u{1F5A5}\uFE0F Opened browser via Electron shell");
} else {
const globalWindow = window;
if (globalWindow.app && typeof globalWindow.app.openExternal === "function") {
globalWindow.app.openExternal(url);
console.log("\u{1F4F1} Opened browser via Obsidian mobile API");
} else {
window.open(url, "_blank");
console.log("\u{1F310} Opened browser via window.open");
}
}
} catch (error) {
console.error("\u274C Failed to open browser:", error);
new import_obsidian.Notice("Failed to open browser. Please open this link manually:");
new import_obsidian.Notice(url);
}
}
/**
* Handle obsidian:// URL callback
* Called by main.ts when URI is opened
*/
handleCallback(uri) {
try {
console.log("\u{1F517} Handling callback URI:", uri);
const url = new URL(uri);
if (!url.pathname.includes("callback")) {
return false;
}
const callbackId = url.searchParams.get("callbackId");
const token = url.searchParams.get("token");
const error = url.searchParams.get("error");
if (error) {
console.error("\u274C Auth callback error:", error);
new import_obsidian.Notice(`\u274C Authentication failed: ${error}`);
this.authCallbacks.clear();
return true;
}
if (!callbackId || !token) {
console.error("\u274C Invalid callback URI: missing callbackId or token");
return false;
}
const callback = this.authCallbacks.get(callbackId);
if (callback) {
console.log("\u2705 Found callback, executing...");
callback(token);
return true;
} else {
console.warn("\u26A0\uFE0F No callback found for callbackId:", callbackId);
return false;
}
} catch (error) {
console.error("\u274C Failed to handle callback:", error);
return false;
}
}
/**
* Sign out
*/
async signOut() {
await auth.signOut();
console.log("\u{1F44B} Signed out");
}
/**
* Get current authenticated user
*/
getCurrentUser() {
const user = auth.currentUser;
if (!user) return null;
return {
uid: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL
};
}
/**
* Get current authenticated user email
*/
getCurrentUserEmail() {
return auth.currentUser?.email || null;
}
/**
* Check if user is authenticated
*/
isAuthenticated() {
return !!auth.currentUser;
}
/**
* Get Firebase ID token
*/
async getIdToken() {
const token = await auth.currentUser?.getIdToken();
if (!token) {
throw new Error("No authentication token available");
}
return token;
}
};
// src/upload-modal.ts
var import_obsidian2 = require("obsidian");
// src/markdown-extractor.ts
var MarkdownExtractor = class {
constructor(app2, vault) {
this.app = app2;
this.vault = vault;
}
/**
* Extract markdown content, images, and internal links from a file
*/
async extractMarkdown(file) {
const content = await this.vault.read(file);
const internalLinks = this.extractInternalLinks(content);
const images = await this.extractImages(content, file);
return {
content,
images,
internalLinks
};
}
/**
* Extract internal links from markdown content
* Matches [[link]] and [[display|link]] patterns
*/
extractInternalLinks(content) {
const regex = /\[\[([^\]]+)\]\]/g;
const links = [];
let match;
while ((match = regex.exec(content)) !== null) {
const startIndex = match.index;
if (startIndex > 0 && content[startIndex - 1] === "!") {
continue;
}
const linkText = match[1];
const parts = linkText.split("|");
const target = parts.length > 1 ? parts[1].trim() : parts[0].trim();
links.push(target);
}
return [...new Set(links)];
}
/**
* Extract and read image files from markdown content
*/
async extractImages(content, sourceFile) {
const images = [];
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)|!\[\[([^\]]+)\]\]/g;
let match;
while ((match = imageRegex.exec(content)) !== null) {
let altText;
let imagePath;
if (match[2]) {
altText = match[1] || void 0;
imagePath = match[2];
} else {
imagePath = match[3];
altText = void 0;
}
try {
const imageFile = this.app.metadataCache.getFirstLinkpathDest(
imagePath,
sourceFile.path
);
if (!imageFile) {
console.warn(`\u26A0\uFE0F Image not found in vault: ${imagePath}`);
console.warn(`Source file path: ${sourceFile.path}`);
console.warn(`Looking for: ${imagePath}`);
continue;
}
const data = await this.vault.readBinary(imageFile);
const mimeType = this.getMimeType(imageFile.extension);
images.push({
name: imageFile.name,
data,
mimeType,
size: data.byteLength,
altText,
originalPath: imagePath
});
console.log(`\u{1F4F7} Extracted image: ${imageFile.name} (${(data.byteLength / 1024).toFixed(1)}KB)`);
} catch (error) {
console.error(`\u274C Failed to read image: ${imagePath}`, error);
}
}
return images;
}
/**
* Get MIME type from file extension
*/
getMimeType(extension) {
const mimeTypes = {
"png": "image/png",
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"gif": "image/gif",
"svg": "image/svg+xml",
"webp": "image/webp",
"bmp": "image/bmp"
};
return mimeTypes[extension.toLowerCase()] || "application/octet-stream";
}
};
// src/image-uploader.ts
init_firebase_config();
init_dist4();
var ImageUploader = class {
/**
* Upload images to Firebase Storage
* @param images Array of images to upload
* @param memoId Memo ID for storage path
* @returns Array of uploaded image metadata
*/
async uploadImages(images, memoId) {
const uploadedImages = [];
for (let i = 0; i < images.length; i++) {
const image = images[i];
try {
console.log(`\u{1F4E4} Uploading image ${i + 1}/${images.length}: ${image.name}...`);
console.log(` Size: ${(image.size / 1024).toFixed(1)}KB`);
console.log(` Type: ${image.mimeType}`);
const timestamp = Date.now();
const sanitizedName = this.sanitizeFileName(image.name);
const storagePath = `memos/${memoId}/images/${timestamp}_${sanitizedName}`;
console.log(` Storage path: ${storagePath}`);
const storageRef = ref(storage, storagePath);
const blob = new Blob([image.data], { type: image.mimeType });
console.log(` Blob created: ${blob.size} bytes`);
console.log(` Starting upload...`);
const snapshot = await uploadBytes(storageRef, blob, {
contentType: image.mimeType
});
const downloadUrl = await getDownloadURL(snapshot.ref);
console.log(` Download URL: ${downloadUrl}`);
uploadedImages.push({
originalName: image.name,
storagePath: snapshot.ref.fullPath,
downloadUrl,
mimeType: image.mimeType,
size: image.size,
altText: image.altText
});
console.log(`\u2705 Image uploaded successfully: ${image.name}`);
} catch (error) {
console.error(`\u274C Failed to upload image: ${image.name}`, error);
console.error("Error code:", error.code);
console.error("Error message:", error.message);
console.error("Full error:", JSON.stringify(error, null, 2));
const errorMsg = error.code === "storage/unauthorized" ? "Storage permission denied. Please check Firebase Storage rules." : error.message || error.code || "Unknown error";
throw new Error(`Failed to upload image: ${image.name}
${errorMsg}`);
}
}
return uploadedImages;
}
/**
* Sanitize file name for storage
*/
sanitizeFileName(fileName) {
return fileName.replace(/[^a-zA-Z0-9._-]/g, "_").replace(/_{2,}/g, "_").toLowerCase();
}
/**
* Replace image paths in markdown content with uploaded URLs
*/
replaceImagePaths(content, originalImages, uploadedImages) {
let updatedContent = content;
for (let i = 0; i < originalImages.length; i++) {
const original = originalImages[i];
const uploaded = uploadedImages[i];
if (!uploaded) continue;
const wikiRegex = new RegExp(`!\\[\\[${this.escapeRegex(original.originalPath)}\\]\\]`, "g");
updatedContent = updatedContent.replace(
wikiRegex,
`![${uploaded.altText || uploaded.originalName}](${uploaded.downloadUrl})`
);
const mdRegex = new RegExp(`!\\[([^\\]]*)\\]\\(${this.escapeRegex(original.originalPath)}\\)`, "g");
updatedContent = updatedContent.replace(
mdRegex,
`![$1](${uploaded.downloadUrl})`
);
}
return updatedContent;
}
/**
* Escape special regex characters
*/
escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
};
// src/memo-uploader.ts
init_firebase_config();
init_dist3();
var MemoUploader = class {
/**
* Create a new Markdown memo
*/
async createMemo(shortCode, password) {
console.log(`\u{1F4DD} Creating memo with shortCode: ${shortCode}`);
if (password) {
console.log(`\u{1F512} Password protection enabled`);
}
const createMemoFunction = httpsCallable(functions, "createMemo");
const request = {
shortCode,
isPublic: true,
contentType: "markdown"
};
if (password) {
request.password = password;
}
const result = await createMemoFunction(request);
const data = result.data;
if (!data.success) {
throw new Error(data.error || "Failed to create memo");
}
console.log(`\u2705 Memo created: ${data.memoId}`);
return {
memoId: data.memoId,
shortCode: data.shortCode
};
}
/**
* Save markdown content to memo
*/
async saveMemo(memoId, shortCode, content, images, internalLinks, version6, password) {
console.log(`\u{1F4BE} Saving memo: ${shortCode}`);
const saveMemoFunction = httpsCallable(functions, "saveMemo");
const request = {
shortCode,
memoId,
markdownData: {
content,
images: images.map((img, index) => ({
id: `img_${index}`,
storagePath: img.storagePath,
originalName: img.originalName,
mimeType: img.mimeType,
size: img.size,
altText: img.altText
})),
internalLinks
},
version: version6
};
if (password) {
request.password = password;
}
const result = await saveMemoFunction(request);
const data = result.data;
if (!data.success) {
throw new Error(data.error || "Failed to save memo");
}
console.log(`\u2705 Memo saved successfully. Version: ${data.version}`);
return {
success: true,
memoId,
shortCode,
url: `https://uuu.gl/md/${shortCode}`,
version: data.version || 0
};
}
/**
* Complete upload workflow: create + save
*/
async uploadMarkdown(shortCode, content, images, internalLinks) {
const { memoId, shortCode: finalShortCode } = await this.createMemo(shortCode);
const result = await this.saveMemo(
memoId,
finalShortCode,
content,
images,
internalLinks,
0
// Initial version
);
return result;
}
};
// src/upload-modal.ts
init_dist3();
init_firebase_config();
var UploadModal = class extends import_obsidian2.Modal {
constructor(app2, file, authManager, plugin, defaultPrefix = "obsidian") {
super(app2);
this.keyword1Input = null;
this.keyword2Input = null;
this.passwordInput = null;
this.urlPreviewEl = null;
this.progressEl = null;
this.progressBar = null;
this.progressText = null;
this.resultEl = null;
this.mainContent = null;
this.existingUrl = null;
this.file = file;
this.authManager = authManager;
this.plugin = plugin;
this.defaultPrefix = defaultPrefix;
}
async onOpen() {
const { contentEl } = this;
contentEl.addClass("uuugl-upload-modal");
const header = contentEl.createDiv({ cls: "uuugl-modal-header" });
header.createEl("h2", { text: "Upload note to uuu.gl" });
header.createEl("p", {
text: `File: ${this.file.basename}`,
cls: "uuugl-file-name"
});
this.mainContent = contentEl.createDiv({ cls: "uuugl-modal-content" });
this.progressEl = contentEl.createDiv({ cls: "uuugl-progress" });
this.progressText = this.progressEl.createDiv({ cls: "uuugl-progress-text" });
const progressBarContainer = this.progressEl.createDiv({ cls: "uuugl-progress-bar-container" });
this.progressBar = progressBarContainer.createDiv({ cls: "uuugl-progress-bar-fill" });
this.progressEl.hide();
this.resultEl = contentEl.createDiv({ cls: "uuugl-result" });
this.resultEl.hide();
this.existingUrl = await this.checkExistingMemo();
if (this.existingUrl) {
this.renderExistingMemoUI(this.existingUrl);
} else {
this.renderNewMemoUI();
}
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
/**
* Check if the file already has a uuu.gl link (memory cache or frontmatter)
*/
async checkExistingMemo() {
try {
const cachedUrl = this.plugin.urlCache.get(this.file.path);
if (cachedUrl) {
console.log("\u2705 Found URL in memory cache:", cachedUrl);
return cachedUrl;
}
const content = await this.app.vault.read(this.file);
const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
const match = content.match(frontmatterRegex);
if (!match) return null;
const frontmatter = match[1];
const lines = frontmatter.split("\n");
for (const line of lines) {
if (line.startsWith("uuugl:")) {
const url = line.replace("uuugl:", "").trim();
if (url) {
this.plugin.setUuuglUrl(this.file, url);
console.log("\u2705 Found URL in frontmatter:", url);
return url;
}
}
}
return null;
} catch (error) {
console.error("Failed to check existing memo:", error);
return null;
}
}
/**
* Render UI for existing memo (Copy/Update/Delete)
*/
renderExistingMemoUI(url) {
if (!this.mainContent) return;
this.mainContent.empty();
const shortCode = url.replace("https://uuu.gl/", "");
const infoSection = this.mainContent.createDiv({ cls: "uuugl-existing-memo-section" });
const infoTitle = infoSection.createEl("div", {
text: "\u2705 This note is already uploaded",
cls: "uuugl-existing-memo-title"
});
const urlDisplay = infoSection.createEl("a", {
text: url,
href: url,
cls: "uuugl-existing-memo-url"
});
urlDisplay.setAttribute("target", "_blank");
const uploadDate = this.mainContent.createDiv({ cls: "uuugl-existing-memo-date" });
uploadDate.setText("\u{1F5D3}\uFE0F You can update the memo content or delete it to create a new one");
this.mainContent.createDiv({ cls: "uuugl-section-divider" });
const buttonsSection = this.mainContent.createDiv({ cls: "uuugl-existing-memo-buttons" });
const copyButton = buttonsSection.createEl("button", {
text: "\u{1F4CE} Copy Link",
cls: "uuugl-btn uuugl-btn-secondary"
});
copyButton.addEventListener("click", () => {
navigator.clipboard.writeText(url);
new import_obsidian2.Notice("\u{1F4CE} Link copied to clipboard!");
});
const updateButton = buttonsSection.createEl("button", {
text: "\u{1F504} Update Memo",
cls: "uuugl-btn uuugl-btn-primary"
});
updateButton.addEventListener("click", () => this.handleUpdateMemo(shortCode));
const deleteButton = buttonsSection.createEl("button", {
text: "\u{1F5D1}\uFE0F Delete Memo",
cls: "uuugl-btn uuugl-btn-danger"
});
deleteButton.addEventListener("click", () => this.handleDeleteMemo(shortCode));
}
/**
* Render UI for new memo upload
*/
renderNewMemoUI() {
if (!this.mainContent) return;
this.mainContent.empty();
const passwordSection = this.mainContent.createDiv({ cls: "setting-item uuugl-setting-item" });
const passwordInfo = passwordSection.createDiv({ cls: "setting-item-info" });
passwordInfo.createDiv({ cls: "setting-item-name", text: "Password protection" });
passwordInfo.createDiv({ cls: "setting-item-description", text: "Optional: Set a password to protect your note" });
const passwordControl = passwordSection.createDiv({ cls: "setting-item-control" });
this.passwordInput = passwordControl.createEl("input", {
type: "password",
placeholder: "Enter password (optional)",
cls: "uuugl-password-input"
});
const divider1 = this.mainContent.createDiv({ cls: "uuugl-section-divider" });
const urlOptionsHeader = this.mainContent.createDiv({ cls: "uuugl-section-header" });
urlOptionsHeader.createEl("h3", { text: "Choose URL type", cls: "uuugl-section-title" });
urlOptionsHeader.createEl("p", {
text: "Create a custom memorable URL or generate a random short code",
cls: "uuugl-section-description"
});
const customUrlSection = this.mainContent.createDiv({ cls: "uuugl-option-section" });
const customUrlLabel = customUrlSection.createDiv({ cls: "uuugl-option-label" });
customUrlLabel.createEl("span", { text: "\u{1F3AF} Custom URL", cls: "uuugl-option-title" });
customUrlLabel.createEl("span", {
text: "keyword1/keyword2",
cls: "uuugl-option-badge"
});
const customUrlDesc = customUrlSection.createDiv({ cls: "uuugl-option-description" });
customUrlDesc.setText("Create a memorable URL with custom keywords");
const urlInputContainer = customUrlSection.createDiv({ cls: "uuugl-url-input-container" });
urlInputContainer.createEl("span", {
text: "uuu.gl/",
cls: "uuugl-url-prefix"
});
this.keyword1Input = urlInputContainer.createEl("input", {
type: "text",
placeholder: "keyword1",
cls: "uuugl-keyword-input"
});
urlInputContainer.createEl("span", {
text: "/",
cls: "uuugl-url-separator"
});
this.keyword2Input = urlInputContainer.createEl("input", {
type: "text",
placeholder: "keyword2",
cls: "uuugl-keyword-input"
});
const customUrlButton = customUrlSection.createEl("button", {
text: "Create Custom URL",
cls: "uuugl-btn uuugl-btn-primary"
});
customUrlButton.addEventListener("click", () => this.handleUpload());
const orDivider = this.mainContent.createDiv({ cls: "uuugl-divider" });
orDivider.createEl("span", { text: "or" });
const randomUrlSection = this.mainContent.createDiv({ cls: "uuugl-option-section" });
const randomUrlLabel = randomUrlSection.createDiv({ cls: "uuugl-option-label" });
randomUrlLabel.createEl("span", { text: "\u{1F3B2} Random URL", cls: "uuugl-option-title" });
randomUrlLabel.createEl("span", {
text: "Quick & easy",
cls: "uuugl-option-badge uuugl-option-badge-secondary"
});
const randomUrlDesc = randomUrlSection.createDiv({ cls: "uuugl-option-description" });
randomUrlDesc.setText("Automatically generate a short random code");
const randomButton = randomUrlSection.createEl("button", {
text: "Generate Random URL",
cls: "uuugl-btn uuugl-btn-secondary"
});
randomButton.addEventListener("click", async () => {
if (this.keyword1Input && this.keyword2Input) {
this.keyword1Input.value = this.generateRandomShortCode();
this.keyword2Input.value = "";
this.updateUrlPreview();
await this.handleUpload();
}
});
const sanitizedName = this.sanitizeShortCode(this.file.basename);
if (this.keyword1Input && this.keyword2Input) {
this.keyword1Input.value = this.defaultPrefix;
this.keyword2Input.value = sanitizedName;
}
this.keyword1Input.addEventListener("input", () => this.updateUrlPreview());
this.keyword2Input.addEventListener("input", () => this.updateUrlPreview());
this.urlPreviewEl = this.contentEl.createDiv({ cls: "uuugl-url-preview" });
this.urlPreviewEl.hide();
if (this.keyword1Input) {
this.keyword1Input.focus();
this.keyword1Input.select();
}
}
/**
* Handle memo update
*/
async handleUpdateMemo(shortCode) {
try {
this.progressEl?.show();
this.resultEl?.hide();
if (this.mainContent) this.mainContent.hide();
this.updateProgress("\u{1F510} Authenticating...", 10);
if (!this.authManager.isAuthenticated()) {
throw new Error("Not authenticated. Please configure your email in settings.");
}
this.updateProgress("\u{1F4C4} Extracting markdown content...", 30);
const extractor = new MarkdownExtractor(this.app, this.app.vault);
const extracted = await extractor.extractMarkdown(this.file);
console.log(`\u{1F4CA} Extracted: ${extracted.images.length} images, ${extracted.internalLinks.length} internal links`);
this.updateProgress("\u{1F50D} Looking up memo...", 50);
const memoUploader = new MemoUploader();
const getMemoFn = httpsCallable(functions, "getMemo");
const getMemoResult = await getMemoFn({ shortCode });
const memoData = getMemoResult.data;
if (!memoData.success || !memoData.memo) {
throw new Error("Memo not found. Unable to update.");
}
const memoId = memoData.memo.memoId;
const currentVersion = memoData.memo.version || 0;
console.log(`\u{1F4DD} Found memo ID: ${memoId}, version: ${currentVersion}`);
let updatedContent = extracted.content;
if (extracted.images.length > 0) {
this.updateProgress(`\u{1F4E4} Uploading ${extracted.images.length} image(s)...`, 70);
const imageUploader = new ImageUploader();
const uploadedImages = await imageUploader.uploadImages(extracted.images, memoId);
updatedContent = imageUploader.replaceImagePaths(
extracted.content,
extracted.images,
uploadedImages
);
}
this.updateProgress("\u{1F4BE} Updating memo...", 90);
await memoUploader.saveMemo(
memoId,
shortCode,
updatedContent,
extracted.images.length > 0 ? [] : [],
extracted.internalLinks,
currentVersion,
// Fix: Pass current version for proper version control
null
// Password not changeable on update
);
this.updateProgress("\u2705 Update complete!", 100);
const displayUrl = `https://uuu.gl/${shortCode}`;
this.plugin.setUuuglUrl(this.file, displayUrl);
await this.plugin.saveUrlCache();
await this.plugin.updateStatusBar();
this.showSuccess(displayUrl, "Memo updated successfully!");
} catch (error) {
console.error("\u274C Update failed:", error);
this.showError(error.message || "Update failed");
if (this.mainContent) this.mainContent.show();
}
}
/**
* Handle memo deletion
*/
async handleDeleteMemo(shortCode) {
try {
const confirmed = confirm(
`Are you sure you want to delete this memo?
URL: https://uuu.gl/${shortCode}
This will remove the memo from uuu.gl and clear the frontmatter. You can then create a new memo with a different URL.`
);
if (!confirmed) return;
this.progressEl?.show();
this.resultEl?.hide();
if (this.mainContent) this.mainContent.hide();
this.updateProgress("\u{1F510} Authenticating...", 20);
if (!this.authManager.isAuthenticated()) {
throw new Error("Not authenticated. Please configure your email in settings.");
}
this.updateProgress("\u{1F5D1}\uFE0F Deleting memo from server...", 50);
const deleteMemoFn = httpsCallable(functions, "deleteMemo");
await deleteMemoFn({ shortCode });
this.updateProgress("\u2705 Deletion complete!", 100);
this.plugin.removeUuuglUrl(this.file);
await this.plugin.saveUrlCache();
await this.plugin.updateStatusBar();
setTimeout(() => {
this.progressEl?.hide();
new import_obsidian2.Notice("\u2705 Memo deleted successfully! You can now create a new one.");
this.existingUrl = null;
this.renderNewMemoUI();
if (this.mainContent) this.mainContent.show();
}, 1e3);
} catch (error) {
console.error("\u274C Deletion failed:", error);
this.showError(error.message || "Deletion failed");
if (this.mainContent) this.mainContent.show();
}
}
updateUrlPreview() {
if (!this.urlPreviewEl || !this.keyword1Input) return;
const keyword1 = this.keyword1Input.value.trim();
const keyword2 = this.keyword2Input?.value.trim() || "";
let previewUrl = "https://uuu.gl/";
if (keyword1 && keyword2) {
previewUrl += `${keyword1}/${keyword2}`;
} else if (keyword1) {
previewUrl += keyword1;
} else {
previewUrl += "[enter-keyword]";
}
this.urlPreviewEl.empty();
this.urlPreviewEl.createEl("span", {
text: `\u{1F4CE} Your note will be accessible at: `,
cls: "upload-modal-url-label"
});
const urlText = this.urlPreviewEl.createEl("span", {
text: previewUrl,
cls: "upload-modal-url-text"
});
urlText.style.fontWeight = "bold";
urlText.style.color = "#5b21b6";
}
async handleUpload() {
if (!this.keyword1Input) return;
const keyword1 = this.keyword1Input.value.trim();
const keyword2 = this.keyword2Input?.value.trim() || "";
const password = this.passwordInput?.value.trim() || null;
if (!keyword1) {
new import_obsidian2.Notice("Please enter keyword1");
return;
}
const shortCode = keyword2 ? `${keyword1}/${keyword2}` : keyword1;
if (!/^[a-zA-Z0-9가-힣_-]+$/.test(keyword1)) {
new import_obsidian2.Notice("Keyword1 can only contain letters, numbers, Korean, _, and -");
return;
}
if (keyword2 && !/^[a-zA-Z0-9가-힣_-]+$/.test(keyword2)) {
new import_obsidian2.Notice("Keyword2 can only contain letters, numbers, Korean, _, and -");
return;
}
try {
this.progressEl?.show();
this.resultEl?.hide();
if (this.mainContent) this.mainContent.hide();
this.updateProgress("\u{1F510} Authenticating...", 10);
if (!this.authManager.isAuthenticated()) {
throw new Error("Not authenticated. Please configure your email in settings.");
}
this.updateProgress("\u{1F4C4} Extracting markdown content...", 30);
const extractor = new MarkdownExtractor(this.app, this.app.vault);
const extracted = await extractor.extractMarkdown(this.file);
console.log(`\u{1F4CA} Extracted: ${extracted.images.length} images, ${extracted.internalLinks.length} internal links`);
if (extracted.images.length > 0) {
console.log("\u{1F4F7} Image details:");
extracted.images.forEach((img, idx) => {
console.log(` ${idx + 1}. ${img.name} (${(img.size / 1024).toFixed(1)}KB, ${img.mimeType})`);
console.log(` Original path: ${img.originalPath}`);
});
}
this.updateProgress("\u{1F4DD} Creating memo...", 50);
const memoUploader = new MemoUploader();
const { memoId } = await memoUploader.createMemo(shortCode, password);
let updatedContent = extracted.content;
if (extracted.images.length > 0) {
this.updateProgress(`\u{1F4E4} Uploading ${extracted.images.length} image(s)...`, 70);
console.log("\u{1F511} User authenticated:", this.authManager.isAuthenticated());
console.log("\u{1F464} Current user:", this.authManager.getCurrentUserEmail());
const imageUploader = new ImageUploader();
const uploadedImages = await imageUploader.uploadImages(extracted.images, memoId);
updatedContent = imageUploader.replaceImagePaths(
extracted.content,
extracted.images,
uploadedImages
);
}
this.updateProgress("\u{1F4BE} Saving memo...", 90);
await memoUploader.saveMemo(
memoId,
shortCode,
updatedContent,
extracted.images.length > 0 ? [] : [],
// Images are already in content as URLs
extracted.internalLinks,
0,
password
);
this.updateProgress("\u2705 Upload complete!", 100);
const displayUrl = `https://uuu.gl/${shortCode}`;
this.plugin.setUuuglUrl(this.file, displayUrl);
await this.plugin.saveUrlCache();
await this.plugin.updateStatusBar();
this.showSuccess(displayUrl, "Note uploaded successfully!");
} catch (error) {
console.error("\u274C Upload failed:", error);
this.showError(error.message || "Upload failed");
if (this.mainContent) this.mainContent.show();
}
}
updateProgress(message, percentage) {
if (this.progressText) {
this.progressText.setText(message);
}
if (this.progressBar && percentage !== void 0) {
this.progressBar.style.width = `${percentage}%`;
}
}
showSuccess(url, message = "Upload successful!") {
if (!this.resultEl) return;
this.progressEl?.hide();
this.resultEl.empty();
this.resultEl.show();
this.resultEl.addClass("uuugl-success-container");
const successHeader = this.resultEl.createDiv({ cls: "uuugl-success-header" });
successHeader.createEl("div", {
text: `\u2705 ${message}`,
cls: "uuugl-success-title"
});
const urlSection = this.resultEl.createDiv({ cls: "uuugl-success-url-section" });
urlSection.createEl("p", {
text: "Your note is now live at:",
cls: "uuugl-success-label"
});
const link = urlSection.createEl("a", {
text: url,
href: url,
cls: "uuugl-success-url"
});
link.setAttribute("target", "_blank");
const buttonContainer = this.resultEl.createDiv({ cls: "uuugl-success-buttons" });
const copyButton = buttonContainer.createEl("button", {
text: "Copy Link",
cls: "uuugl-btn uuugl-btn-primary"
});
copyButton.addEventListener("click", () => {
navigator.clipboard.writeText(url);
new import_obsidian2.Notice("Link copied to clipboard!");
});
const closeButton = buttonContainer.createEl("button", {
text: "Close",
cls: "uuugl-btn uuugl-btn-secondary"
});
closeButton.addEventListener("click", () => this.close());
new import_obsidian2.Notice(`\u2705 ${message}`);
}
showError(message) {
if (!this.resultEl) return;
this.progressEl?.hide();
if (this.mainContent) this.mainContent.hide();
this.resultEl.empty();
this.resultEl.show();
this.resultEl.createEl("div", {
text: `\u274C Failed: ${message}`,
cls: "upload-modal-error"
});
const closeButton = this.resultEl.createEl("button", {
text: "Close"
});
closeButton.addEventListener("click", () => this.close());
new import_obsidian2.Notice(`\u274C Failed: ${message}`);
}
sanitizeShortCode(name6) {
return name6.toLowerCase().replace(/[^a-zA-Z0-9가-힣-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
}
generateRandomShortCode() {
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
let result = "";
for (let i = 0; i < 8; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
};
// src/settings.ts
var import_obsidian3 = require("obsidian");
var DEFAULT_SETTINGS = {
email: "",
uid: "",
fingerprint: "",
lastSyncedAt: "",
defaultShortCodePrefix: "obsidian",
urlCache: {}
// Persistent URL cache
};
var UuuglSettingTab = class extends import_obsidian3.PluginSettingTab {
constructor(app2, plugin) {
super(app2, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h2", { text: "uuu.gl Markdown Uploader Settings" });
containerEl.createEl("p", {
text: "Upload your Obsidian notes to uuu.gl as beautifully rendered Markdown documents.",
cls: "setting-item-description"
});
containerEl.createEl("h3", { text: "Authentication" });
const currentUser = this.plugin.authManager.getCurrentUser();
if (currentUser) {
new import_obsidian3.Setting(containerEl).setName("Logged in as").setDesc(currentUser.email || "No email").addButton(
(button) => button.setButtonText("Sign Out").onClick(async () => {
await this.plugin.authManager.signOut();
this.plugin.settings.email = "";
this.plugin.settings.uid = "";
await this.plugin.saveSettings();
this.display();
})
);
} else {
new import_obsidian3.Setting(containerEl).setName("Google Sign In").setDesc("Sign in with your Google account to upload notes").addButton(
(button) => button.setButtonText("Sign In with Google").setCta().onClick(async () => {
try {
button.setDisabled(true);
button.setButtonText("Signing in...");
const user = await this.plugin.authManager.signInWithGoogle();
if (user.email && user.uid) {
this.plugin.settings.email = user.email;
this.plugin.settings.uid = user.uid;
await this.plugin.saveSettings();
}
this.display();
} catch (error) {
console.error("Sign in failed:", error);
new import_obsidian3.Notice(`\u274C Sign in failed: ${error.message}`);
button.setDisabled(false);
button.setButtonText("Sign In with Google");
}
})
);
}
if (currentUser) {
containerEl.createEl("h3", { text: "Storage Usage" });
const storageContainer = containerEl.createDiv({ cls: "storage-usage-container" });
storageContainer.createEl("p", { text: "Loading storage information..." });
this.fetchStorageStats(storageContainer);
}
new import_obsidian3.Setting(containerEl).setName("Default ShortCode Prefix").setDesc('Prefix for auto-generated shortcodes (e.g., "obsidian/my-note")').addText(
(text) => text.setPlaceholder("obsidian").setValue(this.plugin.settings.defaultShortCodePrefix).onChange(async (value) => {
this.plugin.settings.defaultShortCodePrefix = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Device Fingerprint").setDesc("Unique identifier for this device (auto-generated)").addText(
(text) => text.setValue(this.plugin.settings.fingerprint || "Not generated yet").setDisabled(true)
);
if (this.plugin.settings.lastSyncedAt) {
new import_obsidian3.Setting(containerEl).setName("Last Upload").setDesc("When you last uploaded a note").addText(
(text) => text.setValue(new Date(this.plugin.settings.lastSyncedAt).toLocaleString()).setDisabled(true)
);
}
containerEl.createEl("hr");
containerEl.createEl("h3", { text: "How to Use" });
const instructionsList = containerEl.createEl("ol");
instructionsList.createEl("li", { text: "Enter your email address above" });
instructionsList.createEl("li", { text: "Open any note in Obsidian" });
instructionsList.createEl("li", { text: "Click the upload icon in the ribbon or use the command palette" });
instructionsList.createEl("li", { text: "Choose a shortcode (URL path) for your note" });
instructionsList.createEl("li", { text: "Your note will be uploaded with all images and internal links preserved!" });
containerEl.createEl("p", {
text: "Need help? Visit "
}).createEl("a", {
text: "uuu.gl",
href: "https://uuu.gl"
});
}
/**
* Fetch and display storage statistics
*/
async fetchStorageStats(container) {
try {
const token = await this.plugin.authManager.getIdToken();
const { functions: functions2 } = await Promise.resolve().then(() => (init_firebase_config(), firebase_config_exports));
const { httpsCallable: httpsCallable2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports2));
const getUserStats = httpsCallable2(functions2, "getUserStats");
const result = await getUserStats({});
const stats = result.data;
container.empty();
const formatBytes = (bytes) => {
if (bytes === 0) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
};
const usedBytes = stats.storageUsed || 0;
const limitBytes = stats.storageLimit || 0;
const usedFormatted = formatBytes(usedBytes);
const limitFormatted = limitBytes === -1 ? "Unlimited" : formatBytes(limitBytes);
const percentage = limitBytes === -1 ? 0 : Math.min(100, usedBytes / limitBytes * 100);
new import_obsidian3.Setting(container).setName("Storage Used").setDesc(`${usedFormatted} / ${limitFormatted}`).setClass("storage-stat");
const progressContainer = container.createDiv({ cls: "storage-progress" });
progressContainer.createEl("div", {
cls: "storage-progress-bar",
attr: {
style: `width: ${percentage}%; background-color: ${percentage > 90 ? "#ef4444" : percentage > 70 ? "#f59e0b" : "#22c55e"}`
}
});
new import_obsidian3.Setting(container).setName("Total URLs").setDesc(`${stats.urlCount || 0} URLs created`);
new import_obsidian3.Setting(container).setName("Total Files").setDesc(`${stats.fileCount || 0} files uploaded`);
new import_obsidian3.Setting(container).setName("Total Clicks").setDesc(`${stats.totalClicks || 0} clicks on your URLs`);
if (!document.getElementById("uuugl-storage-styles")) {
const style = document.createElement("style");
style.id = "uuugl-storage-styles";
style.textContent = `
.storage-progress {
width: 100%;
height: 8px;
background-color: var(--background-modifier-border);
border-radius: 4px;
overflow: hidden;
margin: 10px 0;
}
.storage-progress-bar {
height: 100%;
transition: width 0.3s ease;
border-radius: 4px;
}
.storage-usage-container {
padding: 10px 0;
}
`;
document.head.appendChild(style);
}
} catch (error) {
console.error("Failed to fetch storage stats:", error);
container.empty();
container.createEl("p", {
text: "Failed to load storage information",
cls: "mod-warning"
});
}
}
};
// src/main.ts
var import_fingerprintjs = __toESM(require_fp_cjs());
var UuuglPlugin = class extends import_obsidian4.Plugin {
constructor() {
super(...arguments);
this.settings = DEFAULT_SETTINGS;
this.authManager = new AuthManager();
this.fingerprint = "";
this.statusBarItem = null;
// Memory-based URL storage (file path -> uuu.gl URL)
this.urlCache = /* @__PURE__ */ new Map();
}
async onload() {
console.log("\u2705 Loading uuu.gl Markdown Uploader plugin");
await this.loadSettings();
this.restoreUrlCacheFromSettings();
await this.initializeFingerprint();
this.autoReauthenticate().catch((err) => {
console.error("\u274C Background re-authentication failed:", err);
});
this.monitorAuthState();
this.addSettingTab(new UuuglSettingTab(this.app, this));
this.initializeUrlCache().catch((err) => {
console.error("\u274C Failed to initialize URL cache:", err);
});
this.statusBarItem = this.addStatusBarItem();
this.statusBarItem.addClass("uuugl-status-bar");
this.registerEvent(
this.app.workspace.on("active-leaf-change", () => {
this.updateStatusBar();
})
);
this.registerEvent(
this.app.vault.on("modify", (file) => {
const activeFile = this.app.workspace.getActiveFile();
if (file === activeFile) {
this.updateStatusBar();
}
})
);
this.registerObsidianProtocolHandler("uuugl-uploader", (params) => {
console.log("\u{1F517} Received obsidian:// URL:", params);
const uri = `obsidian://uuugl-uploader${params.action ? "/" + params.action : ""}?${new URLSearchParams(params).toString()}`;
const handled = this.authManager.handleCallback(uri);
if (handled) {
console.log("\u2705 Auth callback handled successfully");
}
});
this.addRibbonIcon("upload-cloud", "Upload note to uuu.gl", async () => {
await this.handleUploadCommand();
});
this.addCommand({
id: "upload-markdown",
name: "Upload current note to uuu.gl",
checkCallback: (checking) => {
const activeFile = this.app.workspace.getActiveFile();
if (activeFile) {
if (!checking) {
this.handleUploadCommand();
}
return true;
}
return false;
}
});
this.addCommand({
id: "upload-markdown-custom",
name: "Upload current note with custom shortcode",
checkCallback: (checking) => {
const activeFile = this.app.workspace.getActiveFile();
if (activeFile) {
if (!checking) {
this.openUploadModal(activeFile);
}
return true;
}
return false;
}
});
this.addCommand({
id: "copy-uuugl-link",
name: "Copy uuu.gl link",
checkCallback: (checking) => {
const activeFile = this.app.workspace.getActiveFile();
if (activeFile) {
const url = this.getUuuglLinkFromFile(activeFile);
if (url) {
if (!checking) {
navigator.clipboard.writeText(url);
new import_obsidian4.Notice("\u{1F4CE} uuu.gl link copied to clipboard!");
}
return true;
}
}
return false;
}
});
console.log("\u2705 uuu.gl plugin loaded successfully");
}
async onunload() {
console.log("Unloading uuu.gl plugin");
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
/**
* Restore URL cache from persistent settings storage
*/
restoreUrlCacheFromSettings() {
if (this.settings.urlCache && typeof this.settings.urlCache === "object") {
for (const [filePath, url] of Object.entries(this.settings.urlCache)) {
this.urlCache.set(filePath, url);
}
console.log(`\u2705 Restored ${this.urlCache.size} URLs from persistent storage`);
}
}
/**
* Initialize URL cache by scanning all markdown files for uuugl frontmatter
* (Legacy support - for frontmatter-based storage)
*/
async initializeUrlCache() {
try {
console.log("\u{1F504} Initializing URL cache from frontmatter...");
const files = this.app.vault.getMarkdownFiles();
let cachedCount = 0;
for (const file of files) {
try {
const content = await this.app.vault.read(file);
const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
const match = content.match(frontmatterRegex);
if (!match) continue;
const frontmatter = match[1];
const lines = frontmatter.split("\n");
for (const line of lines) {
if (line.startsWith("uuugl:")) {
const url = line.replace("uuugl:", "").trim();
if (url) {
this.urlCache.set(file.path, url);
cachedCount++;
break;
}
}
}
} catch (error) {
continue;
}
}
console.log(`\u2705 URL cache initialized: ${cachedCount} links found`);
await this.updateStatusBar();
} catch (error) {
console.error("\u274C Failed to initialize URL cache:", error);
}
}
/**
* Initialize device fingerprint for rate limiting
*/
async initializeFingerprint() {
if (this.settings.fingerprint) {
this.fingerprint = this.settings.fingerprint;
console.log("\u{1F511} Loaded existing fingerprint");
return;
}
try {
const fp = await import_fingerprintjs.default.load();
const result = await fp.get();
this.fingerprint = result.visitorId;
this.settings.fingerprint = this.fingerprint;
await this.saveSettings();
console.log("\u{1F511} Fingerprint generated:", this.fingerprint);
} catch (error) {
console.error("\u274C Failed to generate fingerprint:", error);
this.fingerprint = `obsidian-${Date.now()}`;
this.settings.fingerprint = this.fingerprint;
await this.saveSettings();
}
}
/**
* Auto re-authenticate using saved credentials
*/
async autoReauthenticate() {
if (this.authManager.isAuthenticated()) {
console.log("\u2705 Already authenticated");
return;
}
if (this.settings.email && this.settings.uid) {
try {
console.log("\u{1F504} Attempting auto re-authentication for:", this.settings.email);
const { functions: functions2 } = await Promise.resolve().then(() => (init_firebase_config(), firebase_config_exports));
const { httpsCallable: httpsCallable2 } = await Promise.resolve().then(() => (init_dist3(), dist_exports2));
const generateCustomToken = httpsCallable2(functions2, "generateCustomToken");
const result = await generateCustomToken({ email: this.settings.email });
const { customToken } = result.data;
const { auth: auth2 } = await Promise.resolve().then(() => (init_firebase_config(), firebase_config_exports));
const { signInWithCustomToken: signInWithCustomToken2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
await signInWithCustomToken2(auth2, customToken);
console.log("\u2705 Auto re-authentication successful");
} catch (error) {
console.error("\u274C Auto re-authentication failed:", error);
this.settings.email = "";
this.settings.uid = "";
await this.saveSettings();
}
}
}
/**
* Handle upload command
*/
async handleUploadCommand() {
const activeFile = this.app.workspace.getActiveFile();
if (!activeFile) {
new import_obsidian4.Notice("No active file to upload");
return;
}
try {
if (!this.authManager.isAuthenticated()) {
new import_obsidian4.Notice("\u{1F510} Signing in with Google...");
const user = await this.authManager.signInWithGoogle();
if (user.email && user.uid) {
this.settings.email = user.email;
this.settings.uid = user.uid;
await this.saveSettings();
}
new import_obsidian4.Notice(`\u2705 Welcome, ${user.email || "User"}!`);
}
this.openUploadModal(activeFile);
} catch (error) {
console.error("\u274C Authentication failed:", error);
new import_obsidian4.Notice(`\u274C Authentication failed: ${error.message}`);
}
}
/**
* Monitor Firebase authentication state
*/
monitorAuthState() {
const { auth: auth2 } = (init_firebase_config(), __toCommonJS(firebase_config_exports));
const { onAuthStateChanged: onAuthStateChanged2 } = require_index_cjs4();
onAuthStateChanged2(auth2, (user) => {
if (user) {
console.log("\u2705 User authenticated:", user.email);
if (user.email && user.uid) {
if (this.settings.email !== user.email || this.settings.uid !== user.uid) {
this.settings.email = user.email;
this.settings.uid = user.uid;
this.saveSettings();
}
}
} else {
console.log("\u2139\uFE0F No user authenticated");
}
});
}
/**
* Open upload modal
*/
openUploadModal(file) {
const modal = new UploadModal(
this.app,
file,
this.authManager,
this,
// Pass plugin instance
this.settings.defaultShortCodePrefix
);
modal.open();
}
/**
* Update status bar with current file's uuu.gl link
*/
async updateStatusBar() {
if (!this.statusBarItem) return;
const activeFile = this.app.workspace.getActiveFile();
if (!activeFile) {
this.statusBarItem.setText("");
return;
}
const url = await this.getUuuglLinkFromFile(activeFile);
if (url) {
const shortCode = url.replace("https://uuu.gl/", "");
this.statusBarItem.setText(`\u{1F517} ${shortCode}`);
this.statusBarItem.setAttribute("title", `Click to copy: ${url}`);
this.statusBarItem.onclick = () => {
navigator.clipboard.writeText(url);
new import_obsidian4.Notice("\u{1F4CE} uuu.gl link copied to clipboard!");
};
this.statusBarItem.style.cursor = "pointer";
} else {
this.statusBarItem.setText("");
this.statusBarItem.onclick = null;
this.statusBarItem.style.cursor = "default";
}
}
/**
* Get uuu.gl link from memory cache or file's frontmatter
*/
async getUuuglLinkFromFile(file) {
try {
const cachedUrl = this.urlCache.get(file.path);
if (cachedUrl) {
return cachedUrl;
}
const content = await this.app.vault.read(file);
const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
const match = content.match(frontmatterRegex);
if (!match) return null;
const frontmatter = match[1];
const lines = frontmatter.split("\n");
for (const line of lines) {
if (line.startsWith("uuugl:")) {
const url = line.replace("uuugl:", "").trim();
if (url) {
this.urlCache.set(file.path, url);
return url;
}
}
}
return null;
} catch (error) {
console.error("Failed to read uuu.gl link:", error);
return null;
}
}
/**
* Set uuu.gl URL for a file (in memory cache only)
*/
setUuuglUrl(file, url) {
this.urlCache.set(file.path, url);
}
/**
* Remove uuu.gl URL from cache
*/
removeUuuglUrl(file) {
this.urlCache.delete(file.path);
}
/**
* Save URL cache to persistent settings storage
*/
async saveUrlCache() {
const cacheObject = {};
for (const [filePath, url] of this.urlCache.entries()) {
cacheObject[filePath] = url;
}
this.settings.urlCache = cacheObject;
await this.saveSettings();
console.log(`\u{1F4BE} Saved ${this.urlCache.size} URLs to persistent storage`);
}
};
/*! Bundled license information:
@firebase/util/dist/node-esm/index.node.esm.js:
@firebase/util/dist/index.node.cjs.js:
(**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
@firebase/component/dist/esm/index.esm.js:
@firebase/component/dist/index.cjs.js:
(**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
@firebase/logger/dist/esm/index.esm.js:
@firebase/logger/dist/index.cjs.js:
(**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
@firebase/app/dist/esm/index.esm.js:
@firebase/app/dist/index.cjs.js:
(**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
firebase/app/dist/index.mjs:
(**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
@firebase/auth/dist/node-esm/totp-c8d207b9.js:
@firebase/auth/dist/node/totp-50d5d5dd.js:
(**
* @license
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
@firebase/functions/dist/esm/index.esm.js:
(**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
@firebase/storage/dist/node-esm/index.node.esm.js:
(**
* @license
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
*/
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL2Rpc3QvcG9zdGluc3RhbGwubWpzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvY29uc3RhbnRzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvYXNzZXJ0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvY3J5cHQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9kZWVwQ29weS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2dsb2JhbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2RlZmF1bHRzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvZGVmZXJyZWQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy91cmwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9lbXVsYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2Vudmlyb25tZW50LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvZXJyb3JzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvanNvbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2p3dC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL29iai50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL3Byb21pc2UudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9xdWVyeS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL3NoYTEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9zdWJzY3JpYmUudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy92YWxpZGF0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvdXRmOC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2V4cG9uZW50aWFsX2JhY2tvZmYudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9mb3JtYXR0ZXJzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvY29tcGF0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9pbmRleC5ub2RlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvY29tcG9uZW50L3NyYy9jb21wb25lbnQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9jb21wb25lbnQvc3JjL2NvbnN0YW50cy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2NvbXBvbmVudC9zcmMvcHJvdmlkZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9jb21wb25lbnQvc3JjL2NvbXBvbmVudF9jb250YWluZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9sb2dnZXIvc3JjL2xvZ2dlci50cyIsICJub2RlX21vZHVsZXMvaWRiL2J1aWxkL3dyYXAtaWRiLXZhbHVlLmpzIiwgIm5vZGVfbW9kdWxlcy9pZGIvYnVpbGQvaW5kZXguanMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL3BsYXRmb3JtTG9nZ2VyU2VydmljZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvbG9nZ2VyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXBwL3NyYy9jb25zdGFudHMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2ludGVybmFsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXBwL3NyYy9lcnJvcnMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2ZpcmViYXNlQXBwLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXBwL3NyYy9maXJlYmFzZVNlcnZlckFwcC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvYXBpLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXBwL3NyYy9pbmRleGVkZGIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2hlYXJ0YmVhdFNlcnZpY2UudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL3JlZ2lzdGVyQ29yZUNvbXBvbmVudHMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2luZGV4LnRzIiwgIm5vZGVfbW9kdWxlcy9maXJlYmFzZS9hcHAvaW5kZXgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tb2RlbC9lbnVtX21hcHMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2Vycm9ycy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9sb2cudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3V0aWwvYXNzZXJ0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL2xvY2F0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL25hdmlnYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9kZWxheS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9lbXVsYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9mZXRjaF9wcm92aWRlci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2FwaS9lcnJvcnMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvaW5kZXgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9wbGF0Zm9ybV9icm93c2VyL3JlY2FwdGNoYS9yZWNhcHRjaGEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vcmVjYXB0Y2hhLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL3RpbWUudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3VzZXIvaWRfdG9rZW5fcmVzdWx0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL2ludmFsaWRhdGlvbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9wcm9hY3RpdmVfcmVmcmVzaC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci91c2VyX21ldGFkYXRhLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL3JlbG9hZC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2FwaS9hdXRoZW50aWNhdGlvbi90b2tlbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci90b2tlbl9tYW5hZ2VyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL3VzZXJfaW1wbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9pbnN0YW50aWF0b3IudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3BlcnNpc3RlbmNlL2luX21lbW9yeS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvcGVyc2lzdGVuY2UvcGVyc2lzdGVuY2VfdXNlcl9tYW5hZ2VyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL2Jyb3dzZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3V0aWwvdmVyc2lvbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvYXV0aC9taWRkbGV3YXJlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL3Bhc3N3b3JkX3BvbGljeS9nZXRfcGFzc3dvcmRfcG9saWN5LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9hdXRoL3Bhc3N3b3JkX3BvbGljeV9pbXBsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9hdXRoL2F1dGhfaW1wbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL3BsYXRmb3JtX2Jyb3dzZXIvbG9hZF9qcy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL3BsYXRmb3JtX2Jyb3dzZXIvcmVjYXB0Y2hhL3JlY2FwdGNoYV9tb2NrLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2F1dGgvaW5pdGlhbGl6ZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvYXV0aC9lbXVsYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvY3JlZGVudGlhbHMvYXV0aF9jcmVkZW50aWFsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9lbWFpbF9hbmRfcGFzc3dvcmQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vZW1haWxfYW5kX3Bhc3N3b3JkLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2xpbmsudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2NyZWRlbnRpYWxzL2VtYWlsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL2lkcC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvY3JlZGVudGlhbHMvb2F1dGgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vc21zLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9jcmVkZW50aWFscy9waG9uZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvYWN0aW9uX2NvZGVfdXJsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvZW1haWwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3Byb3ZpZGVycy9mZWRlcmF0ZWQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3Byb3ZpZGVycy9vYXV0aC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvcHJvdmlkZXJzL2ZhY2Vib29rLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvZ29vZ2xlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvZ2l0aHViLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9jcmVkZW50aWFscy9zYW1sLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvc2FtbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvcHJvdmlkZXJzL3R3aXR0ZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vc2lnbl91cC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci91c2VyX2NyZWRlbnRpYWxfaW1wbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvc3RyYXRlZ2llcy9hbm9ueW1vdXMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX2Vycm9yLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL3Byb3ZpZGVycy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9saW5rX3VubGluay50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9yZWF1dGhlbnRpY2F0ZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvc3RyYXRlZ2llcy9jcmVkZW50aWFsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL2N1c3RvbV90b2tlbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvc3RyYXRlZ2llcy9jdXN0b21fdG9rZW4udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX2luZm8udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3N0cmF0ZWdpZXMvYWN0aW9uX2NvZGVfc2V0dGluZ3MudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3N0cmF0ZWdpZXMvZW1haWxfYW5kX3Bhc3N3b3JkLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9zdHJhdGVnaWVzL2VtYWlsX2xpbmsudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vY3JlYXRlX2F1dGhfdXJpLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9zdHJhdGVnaWVzL2VtYWlsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9wcm9maWxlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL2FjY291bnRfaW5mby50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9hZGRpdGlvbmFsX3VzZXJfaW5mby50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvaW5kZXgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX3Nlc3Npb24udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX3Jlc29sdmVyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9tZmEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX3VzZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2F1dGgvZmlyZWJhc2VfaW50ZXJuYWwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2F1dGgvcmVnaXN0ZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9wbGF0Zm9ybV9ub2RlL2luZGV4LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL21mYS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL21mYS9tZmFfYXNzZXJ0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvbWZhL2Fzc2VydGlvbnMvdG90cC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvZGlzdC9ub2RlLWVzbS9pbmRleC5qcyIsICJub2RlX21vZHVsZXMvZmlyZWJhc2UvYXV0aC9kaXN0L2luZGV4Lm1qcyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2Z1bmN0aW9ucy9zcmMvc2VyaWFsaXplci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2Z1bmN0aW9ucy9zcmMvY29uc3RhbnRzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvZnVuY3Rpb25zL3NyYy9lcnJvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2Z1bmN0aW9ucy9zcmMvY29udGV4dC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2Z1bmN0aW9ucy9zcmMvc2VydmljZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2Z1bmN0aW9ucy9zcmMvY29uZmlnLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvZnVuY3Rpb25zL3NyYy9hcGkudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9mdW5jdGlvbnMvc3JjL2luZGV4LnRzIiwgIm5vZGVfbW9kdWxlcy9maXJlYmFzZS9mdW5jdGlvbnMvZGlzdC9pbmRleC5tanMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9jb25zdGFudHMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9lcnJvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL2xvY2F0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vZmFpbHJlcXVlc3QudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9iYWNrb2ZmLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vdHlwZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL3VybC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL2Nvbm5lY3Rpb24udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi91dGlscy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL3JlcXVlc3QudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9mcy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL3BsYXRmb3JtL25vZGUvYmFzZTY0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vc3RyaW5nLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vYmxvYi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL2pzb24udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9wYXRoLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vbWV0YWRhdGEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9saXN0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vcmVxdWVzdGluZm8udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9pbXBsZW1lbnRhdGlvbi9yZXF1ZXN0cy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL3Rhc2tlbnVtcy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2ltcGxlbWVudGF0aW9uL29ic2VydmVyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW1wbGVtZW50YXRpb24vYXN5bmMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy9wbGF0Zm9ybS9ub2RlL2Nvbm5lY3Rpb24udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9zdG9yYWdlL3NyYy90YXNrLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvcmVmZXJlbmNlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvc2VydmljZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2NvbnN0YW50cy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2FwaS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3N0b3JhZ2Uvc3JjL2FwaS5ub2RlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2Uvc3RvcmFnZS9zcmMvaW5kZXgubm9kZS50cyIsICJub2RlX21vZHVsZXMvZmlyZWJhc2Uvc3RvcmFnZS9kaXN0L2luZGV4Lm1qcyIsICJzcmMvZmlyZWJhc2UtY29uZmlnLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2Rpc3QvZnAuY2pzLmpzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9kaXN0L3Bvc3RpbnN0YWxsLmpzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvY29uc3RhbnRzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvYXNzZXJ0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvY3J5cHQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9kZWVwQ29weS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2dsb2JhbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2RlZmF1bHRzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvZGVmZXJyZWQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy91cmwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9lbXVsYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2Vudmlyb25tZW50LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvZXJyb3JzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvanNvbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2p3dC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL29iai50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL3Byb21pc2UudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9xdWVyeS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL3NoYTEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9zdWJzY3JpYmUudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy92YWxpZGF0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvdXRmOC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL3V0aWwvc3JjL2V4cG9uZW50aWFsX2JhY2tvZmYudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS91dGlsL3NyYy9mb3JtYXR0ZXJzLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9zcmMvY29tcGF0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvdXRpbC9pbmRleC5ub2RlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvY29tcG9uZW50L3NyYy9jb21wb25lbnQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9jb21wb25lbnQvc3JjL2NvbnN0YW50cy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2NvbXBvbmVudC9zcmMvcHJvdmlkZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9jb21wb25lbnQvc3JjL2NvbXBvbmVudF9jb250YWluZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9sb2dnZXIvc3JjL2xvZ2dlci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvcGxhdGZvcm1Mb2dnZXJTZXJ2aWNlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXBwL3NyYy9sb2dnZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2NvbnN0YW50cy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvaW50ZXJuYWwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2Vycm9ycy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvZmlyZWJhc2VBcHAudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2ZpcmViYXNlU2VydmVyQXBwLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXBwL3NyYy9hcGkudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hcHAvc3JjL2luZGV4ZWRkYi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvaGVhcnRiZWF0U2VydmljZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvcmVnaXN0ZXJDb3JlQ29tcG9uZW50cy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2FwcC9zcmMvaW5kZXgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tb2RlbC9lbnVtX21hcHMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2Vycm9ycy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9sb2cudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3V0aWwvYXNzZXJ0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL2xvY2F0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL25hdmlnYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9kZWxheS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9lbXVsYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9mZXRjaF9wcm92aWRlci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2FwaS9lcnJvcnMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvaW5kZXgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9wbGF0Zm9ybV9icm93c2VyL3JlY2FwdGNoYS9yZWNhcHRjaGEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vcmVjYXB0Y2hhLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL3RpbWUudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3VzZXIvaWRfdG9rZW5fcmVzdWx0LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL2ludmFsaWRhdGlvbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9wcm9hY3RpdmVfcmVmcmVzaC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci91c2VyX21ldGFkYXRhLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL3JlbG9hZC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2FwaS9hdXRoZW50aWNhdGlvbi90b2tlbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci90b2tlbl9tYW5hZ2VyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL3VzZXJfaW1wbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXRpbC9pbnN0YW50aWF0b3IudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3BlcnNpc3RlbmNlL2luX21lbW9yeS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvcGVyc2lzdGVuY2UvcGVyc2lzdGVuY2VfdXNlcl9tYW5hZ2VyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL2Jyb3dzZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3V0aWwvdmVyc2lvbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvYXV0aC9taWRkbGV3YXJlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL3Bhc3N3b3JkX3BvbGljeS9nZXRfcGFzc3dvcmRfcG9saWN5LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9hdXRoL3Bhc3N3b3JkX3BvbGljeV9pbXBsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9hdXRoL2F1dGhfaW1wbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL3BsYXRmb3JtX2Jyb3dzZXIvbG9hZF9qcy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL3BsYXRmb3JtX2Jyb3dzZXIvcmVjYXB0Y2hhL3JlY2FwdGNoYV9tb2NrLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2F1dGgvaW5pdGlhbGl6ZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvYXV0aC9lbXVsYXRvci50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvY3JlZGVudGlhbHMvYXV0aF9jcmVkZW50aWFsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9lbWFpbF9hbmRfcGFzc3dvcmQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vZW1haWxfYW5kX3Bhc3N3b3JkLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2xpbmsudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2NyZWRlbnRpYWxzL2VtYWlsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL2lkcC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvY3JlZGVudGlhbHMvb2F1dGgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vc21zLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9jcmVkZW50aWFscy9waG9uZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvYWN0aW9uX2NvZGVfdXJsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvZW1haWwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3Byb3ZpZGVycy9mZWRlcmF0ZWQudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3Byb3ZpZGVycy9vYXV0aC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvcHJvdmlkZXJzL2ZhY2Vib29rLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvZ29vZ2xlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvZ2l0aHViLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9jcmVkZW50aWFscy9zYW1sLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9wcm92aWRlcnMvc2FtbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvcHJvdmlkZXJzL3R3aXR0ZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vc2lnbl91cC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci91c2VyX2NyZWRlbnRpYWxfaW1wbC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvc3RyYXRlZ2llcy9hbm9ueW1vdXMudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX2Vycm9yLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91dGlsL3Byb3ZpZGVycy50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9saW5rX3VubGluay50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9yZWF1dGhlbnRpY2F0ZS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvc3RyYXRlZ2llcy9jcmVkZW50aWFsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL2N1c3RvbV90b2tlbi50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvc3RyYXRlZ2llcy9jdXN0b21fdG9rZW4udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX2luZm8udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3N0cmF0ZWdpZXMvYWN0aW9uX2NvZGVfc2V0dGluZ3MudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL3N0cmF0ZWdpZXMvZW1haWxfYW5kX3Bhc3N3b3JkLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9zdHJhdGVnaWVzL2VtYWlsX2xpbmsudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9hcGkvYXV0aGVudGljYXRpb24vY3JlYXRlX2F1dGhfdXJpLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS9zdHJhdGVnaWVzL2VtYWlsLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9wcm9maWxlLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvY29yZS91c2VyL2FjY291bnRfaW5mby50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvdXNlci9hZGRpdGlvbmFsX3VzZXJfaW5mby50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL2NvcmUvaW5kZXgudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX3Nlc3Npb24udHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX3Jlc29sdmVyLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2FjY291bnRfbWFuYWdlbWVudC9tZmEudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9tZmEvbWZhX3VzZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2F1dGgvZmlyZWJhc2VfaW50ZXJuYWwudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9jb3JlL2F1dGgvcmVnaXN0ZXIudHMiLCAibm9kZV9tb2R1bGVzL0BmaXJlYmFzZS9hdXRoL3NyYy9wbGF0Zm9ybV9ub2RlL2luZGV4LnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvYXBpL2F1dGhlbnRpY2F0aW9uL21mYS50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvc3JjL21mYS9tZmFfYXNzZXJ0aW9uLnRzIiwgIm5vZGVfbW9kdWxlcy9AZmlyZWJhc2UvYXV0aC9zcmMvbWZhL2Fzc2VydGlvbnMvdG90cC50cyIsICJub2RlX21vZHVsZXMvQGZpcmViYXNlL2F1dGgvZGlzdC9ub2RlL2luZGV4LmpzIiwgIm5vZGVfbW9kdWxlcy9maXJlYmFzZS9hdXRoL2Rpc3QvaW5kZXguY2pzLmpzIiwgInNyYy9tYWluLnRzIiwgInNyYy9hdXRoLW1hbmFnZXIudHMiLCAic3JjL3VwbG9hZC1tb2RhbC50cyIsICJzcmMvbWFya2Rvd24tZXh0cmFjdG9yLnRzIiwgInNyYy9pbWFnZS11cGxvYWRlci50cyIsICJzcmMvbWVtby11cGxvYWRlci50cyIsICJzcmMvc2V0dGluZ3MudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IGdldERlZmF1bHRzRnJvbVBvc3RpbnN0YWxsID0gKCkgPT4gKHVuZGVmaW5lZCk7XG5leHBvcnQgeyBnZXREZWZhdWx0c0Zyb21Qb3N0aW5zdGFsbCB9OyIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgRmlyZWJhc2UgY29uc3RhbnRzLiAgU29tZSBvZiB0aGVzZSAoQGRlZmluZXMpIGNhbiBiZSBvdmVycmlkZGVuIGF0IGNvbXBpbGUtdGltZS5cbiAqL1xuXG5leHBvcnQgY29uc3QgQ09OU1RBTlRTID0ge1xuICAvKipcbiAgICogQGRlZmluZSB7Ym9vbGVhbn0gV2hldGhlciB0aGlzIGlzIHRoZSBjbGllbnQgTm9kZS5qcyBTREsuXG4gICAqL1xuICBOT0RFX0NMSUVOVDogZmFsc2UsXG4gIC8qKlxuICAgKiBAZGVmaW5lIHtib29sZWFufSBXaGV0aGVyIHRoaXMgaXMgdGhlIEFkbWluIE5vZGUuanMgU0RLLlxuICAgKi9cbiAgTk9ERV9BRE1JTjogZmFsc2UsXG5cbiAgLyoqXG4gICAqIEZpcmViYXNlIFNESyBWZXJzaW9uXG4gICAqL1xuICBTREtfVkVSU0lPTjogJyR7SlNDT1JFX1ZFUlNJT059J1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBDT05TVEFOVFMgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbi8qKlxuICogVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBwcm92aWRlZCBhc3NlcnRpb24gaXMgZmFsc3lcbiAqL1xuZXhwb3J0IGNvbnN0IGFzc2VydCA9IGZ1bmN0aW9uIChhc3NlcnRpb246IHVua25vd24sIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICBpZiAoIWFzc2VydGlvbikge1xuICAgIHRocm93IGFzc2VydGlvbkVycm9yKG1lc3NhZ2UpO1xuICB9XG59O1xuXG4vKipcbiAqIFJldHVybnMgYW4gRXJyb3Igb2JqZWN0IHN1aXRhYmxlIGZvciB0aHJvd2luZy5cbiAqL1xuZXhwb3J0IGNvbnN0IGFzc2VydGlvbkVycm9yID0gZnVuY3Rpb24gKG1lc3NhZ2U6IHN0cmluZyk6IEVycm9yIHtcbiAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICAnRmlyZWJhc2UgRGF0YWJhc2UgKCcgK1xuICAgICAgQ09OU1RBTlRTLlNES19WRVJTSU9OICtcbiAgICAgICcpIElOVEVSTkFMIEFTU0VSVCBGQUlMRUQ6ICcgK1xuICAgICAgbWVzc2FnZVxuICApO1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5jb25zdCBzdHJpbmdUb0J5dGVBcnJheSA9IGZ1bmN0aW9uIChzdHI6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgLy8gVE9ETyh1c2VyKTogVXNlIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbnMgaWYvd2hlbiBhdmFpbGFibGVcbiAgY29uc3Qgb3V0OiBudW1iZXJbXSA9IFtdO1xuICBsZXQgcCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGMgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgb3V0W3ArK10gPSBjO1xuICAgIH0gZWxzZSBpZiAoYyA8IDIwNDgpIHtcbiAgICAgIG91dFtwKytdID0gKGMgPj4gNikgfCAxOTI7XG4gICAgICBvdXRbcCsrXSA9IChjICYgNjMpIHwgMTI4O1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICAoYyAmIDB4ZmMwMCkgPT09IDB4ZDgwMCAmJlxuICAgICAgaSArIDEgPCBzdHIubGVuZ3RoICYmXG4gICAgICAoc3RyLmNoYXJDb2RlQXQoaSArIDEpICYgMHhmYzAwKSA9PT0gMHhkYzAwXG4gICAgKSB7XG4gICAgICAvLyBTdXJyb2dhdGUgUGFpclxuICAgICAgYyA9IDB4MTAwMDAgKyAoKGMgJiAweDAzZmYpIDw8IDEwKSArIChzdHIuY2hhckNvZGVBdCgrK2kpICYgMHgwM2ZmKTtcbiAgICAgIG91dFtwKytdID0gKGMgPj4gMTgpIHwgMjQwO1xuICAgICAgb3V0W3ArK10gPSAoKGMgPj4gMTIpICYgNjMpIHwgMTI4O1xuICAgICAgb3V0W3ArK10gPSAoKGMgPj4gNikgJiA2MykgfCAxMjg7XG4gICAgICBvdXRbcCsrXSA9IChjICYgNjMpIHwgMTI4O1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXRbcCsrXSA9IChjID4+IDEyKSB8IDIyNDtcbiAgICAgIG91dFtwKytdID0gKChjID4+IDYpICYgNjMpIHwgMTI4O1xuICAgICAgb3V0W3ArK10gPSAoYyAmIDYzKSB8IDEyODtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogVHVybnMgYW4gYXJyYXkgb2YgbnVtYmVycyBpbnRvIHRoZSBzdHJpbmcgZ2l2ZW4gYnkgdGhlIGNvbmNhdGVuYXRpb24gb2YgdGhlXG4gKiBjaGFyYWN0ZXJzIHRvIHdoaWNoIHRoZSBudW1iZXJzIGNvcnJlc3BvbmQuXG4gKiBAcGFyYW0gYnl0ZXMgQXJyYXkgb2YgbnVtYmVycyByZXByZXNlbnRpbmcgY2hhcmFjdGVycy5cbiAqIEByZXR1cm4gU3RyaW5naWZpY2F0aW9uIG9mIHRoZSBhcnJheS5cbiAqL1xuY29uc3QgYnl0ZUFycmF5VG9TdHJpbmcgPSBmdW5jdGlvbiAoYnl0ZXM6IG51bWJlcltdKTogc3RyaW5nIHtcbiAgLy8gVE9ETyh1c2VyKTogVXNlIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbnMgaWYvd2hlbiBhdmFpbGFibGVcbiAgY29uc3Qgb3V0OiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgcG9zID0gMCxcbiAgICBjID0gMDtcbiAgd2hpbGUgKHBvcyA8IGJ5dGVzLmxlbmd0aCkge1xuICAgIGNvbnN0IGMxID0gYnl0ZXNbcG9zKytdO1xuICAgIGlmIChjMSA8IDEyOCkge1xuICAgICAgb3V0W2MrK10gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMxKTtcbiAgICB9IGVsc2UgaWYgKGMxID4gMTkxICYmIGMxIDwgMjI0KSB7XG4gICAgICBjb25zdCBjMiA9IGJ5dGVzW3BvcysrXTtcbiAgICAgIG91dFtjKytdID0gU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMxICYgMzEpIDw8IDYpIHwgKGMyICYgNjMpKTtcbiAgICB9IGVsc2UgaWYgKGMxID4gMjM5ICYmIGMxIDwgMzY1KSB7XG4gICAgICAvLyBTdXJyb2dhdGUgUGFpclxuICAgICAgY29uc3QgYzIgPSBieXRlc1twb3MrK107XG4gICAgICBjb25zdCBjMyA9IGJ5dGVzW3BvcysrXTtcbiAgICAgIGNvbnN0IGM0ID0gYnl0ZXNbcG9zKytdO1xuICAgICAgY29uc3QgdSA9XG4gICAgICAgICgoKGMxICYgNykgPDwgMTgpIHwgKChjMiAmIDYzKSA8PCAxMikgfCAoKGMzICYgNjMpIDw8IDYpIHwgKGM0ICYgNjMpKSAtXG4gICAgICAgIDB4MTAwMDA7XG4gICAgICBvdXRbYysrXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhkODAwICsgKHUgPj4gMTApKTtcbiAgICAgIG91dFtjKytdID0gU3RyaW5nLmZyb21DaGFyQ29kZSgweGRjMDAgKyAodSAmIDEwMjMpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgYzIgPSBieXRlc1twb3MrK107XG4gICAgICBjb25zdCBjMyA9IGJ5dGVzW3BvcysrXTtcbiAgICAgIG91dFtjKytdID0gU3RyaW5nLmZyb21DaGFyQ29kZShcbiAgICAgICAgKChjMSAmIDE1KSA8PCAxMikgfCAoKGMyICYgNjMpIDw8IDYpIHwgKGMzICYgNjMpXG4gICAgICApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0LmpvaW4oJycpO1xufTtcblxuaW50ZXJmYWNlIEJhc2U2NCB7XG4gIGJ5dGVUb0NoYXJNYXBfOiB7IFtrZXk6IG51bWJlcl06IHN0cmluZyB9IHwgbnVsbDtcbiAgY2hhclRvQnl0ZU1hcF86IHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0gfCBudWxsO1xuICBieXRlVG9DaGFyTWFwV2ViU2FmZV86IHsgW2tleTogbnVtYmVyXTogc3RyaW5nIH0gfCBudWxsO1xuICBjaGFyVG9CeXRlTWFwV2ViU2FmZV86IHsgW2tleTogc3RyaW5nXTogbnVtYmVyIH0gfCBudWxsO1xuICBFTkNPREVEX1ZBTFNfQkFTRTogc3RyaW5nO1xuICByZWFkb25seSBFTkNPREVEX1ZBTFM6IHN0cmluZztcbiAgcmVhZG9ubHkgRU5DT0RFRF9WQUxTX1dFQlNBRkU6IHN0cmluZztcbiAgSEFTX05BVElWRV9TVVBQT1JUOiBib29sZWFuO1xuICBlbmNvZGVCeXRlQXJyYXkoaW5wdXQ6IG51bWJlcltdIHwgVWludDhBcnJheSwgd2ViU2FmZT86IGJvb2xlYW4pOiBzdHJpbmc7XG4gIGVuY29kZVN0cmluZyhpbnB1dDogc3RyaW5nLCB3ZWJTYWZlPzogYm9vbGVhbik6IHN0cmluZztcbiAgZGVjb2RlU3RyaW5nKGlucHV0OiBzdHJpbmcsIHdlYlNhZmU6IGJvb2xlYW4pOiBzdHJpbmc7XG4gIGRlY29kZVN0cmluZ1RvQnl0ZUFycmF5KGlucHV0OiBzdHJpbmcsIHdlYlNhZmU6IGJvb2xlYW4pOiBudW1iZXJbXTtcbiAgaW5pdF8oKTogdm9pZDtcbn1cblxuLy8gV2UgZGVmaW5lIGl0IGFzIGFuIG9iamVjdCBsaXRlcmFsIGluc3RlYWQgb2YgYSBjbGFzcyBiZWNhdXNlIGEgY2xhc3MgY29tcGlsZWQgZG93biB0byBlczUgY2FuJ3Rcbi8vIGJlIHRyZWVzaGFrZWQuIGh0dHBzOi8vZ2l0aHViLmNvbS9yb2xsdXAvcm9sbHVwL2lzc3Vlcy8xNjkxXG4vLyBTdGF0aWMgbG9va3VwIG1hcHMsIGxhemlseSBwb3B1bGF0ZWQgYnkgaW5pdF8oKVxuLy8gVE9ETyhkbGFyb2NxdWUpOiBEZWZpbmUgdGhpcyBhcyBhIGNsYXNzLCBzaW5jZSB3ZSBubyBsb25nZXIgdGFyZ2V0IEVTNS5cbmV4cG9ydCBjb25zdCBiYXNlNjQ6IEJhc2U2NCA9IHtcbiAgLyoqXG4gICAqIE1hcHMgYnl0ZXMgdG8gY2hhcmFjdGVycy5cbiAgICovXG4gIGJ5dGVUb0NoYXJNYXBfOiBudWxsLFxuXG4gIC8qKlxuICAgKiBNYXBzIGNoYXJhY3RlcnMgdG8gYnl0ZXMuXG4gICAqL1xuICBjaGFyVG9CeXRlTWFwXzogbnVsbCxcblxuICAvKipcbiAgICogTWFwcyBieXRlcyB0byB3ZWJzYWZlIGNoYXJhY3RlcnMuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBieXRlVG9DaGFyTWFwV2ViU2FmZV86IG51bGwsXG5cbiAgLyoqXG4gICAqIE1hcHMgd2Vic2FmZSBjaGFyYWN0ZXJzIHRvIGJ5dGVzLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY2hhclRvQnl0ZU1hcFdlYlNhZmVfOiBudWxsLFxuXG4gIC8qKlxuICAgKiBPdXIgZGVmYXVsdCBhbHBoYWJldCwgc2hhcmVkIGJldHdlZW5cbiAgICogRU5DT0RFRF9WQUxTIGFuZCBFTkNPREVEX1ZBTFNfV0VCU0FGRVxuICAgKi9cbiAgRU5DT0RFRF9WQUxTX0JBU0U6XG4gICAgJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaJyArICdhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eicgKyAnMDEyMzQ1Njc4OScsXG5cbiAgLyoqXG4gICAqIE91ciBkZWZhdWx0IGFscGhhYmV0LiBWYWx1ZSA2NCAoPSkgaXMgc3BlY2lhbDsgaXQgbWVhbnMgXCJub3RoaW5nLlwiXG4gICAqL1xuICBnZXQgRU5DT0RFRF9WQUxTKCkge1xuICAgIHJldHVybiB0aGlzLkVOQ09ERURfVkFMU19CQVNFICsgJysvPSc7XG4gIH0sXG5cbiAgLyoqXG4gICAqIE91ciB3ZWJzYWZlIGFscGhhYmV0LlxuICAgKi9cbiAgZ2V0IEVOQ09ERURfVkFMU19XRUJTQUZFKCkge1xuICAgIHJldHVybiB0aGlzLkVOQ09ERURfVkFMU19CQVNFICsgJy1fLic7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBicm93c2VyIHN1cHBvcnRzIHRoZSBhdG9iIGFuZCBidG9hIGZ1bmN0aW9ucy4gVGhpcyBleHRlbnNpb25cbiAgICogc3RhcnRlZCBhdCBNb3ppbGxhIGJ1dCBpcyBub3cgaW1wbGVtZW50ZWQgYnkgbWFueSBicm93c2Vycy4gV2UgdXNlIHRoZVxuICAgKiBBU1NVTUVfKiB2YXJpYWJsZXMgdG8gYXZvaWQgcHVsbGluZyBpbiB0aGUgZnVsbCB1c2VyYWdlbnQgZGV0ZWN0aW9uIGxpYnJhcnlcbiAgICogYnV0IHN0aWxsIGFsbG93aW5nIHRoZSBzdGFuZGFyZCBwZXItYnJvd3NlciBjb21waWxhdGlvbnMuXG4gICAqXG4gICAqL1xuICBIQVNfTkFUSVZFX1NVUFBPUlQ6IHR5cGVvZiBhdG9iID09PSAnZnVuY3Rpb24nLFxuXG4gIC8qKlxuICAgKiBCYXNlNjQtZW5jb2RlIGFuIGFycmF5IG9mIGJ5dGVzLlxuICAgKlxuICAgKiBAcGFyYW0gaW5wdXQgQW4gYXJyYXkgb2YgYnl0ZXMgKG51bWJlcnMgd2l0aFxuICAgKiAgICAgdmFsdWUgaW4gWzAsIDI1NV0pIHRvIGVuY29kZS5cbiAgICogQHBhcmFtIHdlYlNhZmUgQm9vbGVhbiBpbmRpY2F0aW5nIHdlIHNob3VsZCB1c2UgdGhlXG4gICAqICAgICBhbHRlcm5hdGl2ZSBhbHBoYWJldC5cbiAgICogQHJldHVybiBUaGUgYmFzZTY0IGVuY29kZWQgc3RyaW5nLlxuICAgKi9cbiAgZW5jb2RlQnl0ZUFycmF5KGlucHV0OiBudW1iZXJbXSB8IFVpbnQ4QXJyYXksIHdlYlNhZmU/OiBib29sZWFuKTogc3RyaW5nIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICB0aHJvdyBFcnJvcignZW5jb2RlQnl0ZUFycmF5IHRha2VzIGFuIGFycmF5IGFzIGEgcGFyYW1ldGVyJyk7XG4gICAgfVxuXG4gICAgdGhpcy5pbml0XygpO1xuXG4gICAgY29uc3QgYnl0ZVRvQ2hhck1hcCA9IHdlYlNhZmVcbiAgICAgID8gdGhpcy5ieXRlVG9DaGFyTWFwV2ViU2FmZV8hXG4gICAgICA6IHRoaXMuYnl0ZVRvQ2hhck1hcF8hO1xuXG4gICAgY29uc3Qgb3V0cHV0ID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Lmxlbmd0aDsgaSArPSAzKSB7XG4gICAgICBjb25zdCBieXRlMSA9IGlucHV0W2ldO1xuICAgICAgY29uc3QgaGF2ZUJ5dGUyID0gaSArIDEgPCBpbnB1dC5sZW5ndGg7XG4gICAgICBjb25zdCBieXRlMiA9IGhhdmVCeXRlMiA/IGlucHV0W2kgKyAxXSA6IDA7XG4gICAgICBjb25zdCBoYXZlQnl0ZTMgPSBpICsgMiA8IGlucHV0Lmxlbmd0aDtcbiAgICAgIGNvbnN0IGJ5dGUzID0gaGF2ZUJ5dGUzID8gaW5wdXRbaSArIDJdIDogMDtcblxuICAgICAgY29uc3Qgb3V0Qnl0ZTEgPSBieXRlMSA+PiAyO1xuICAgICAgY29uc3Qgb3V0Qnl0ZTIgPSAoKGJ5dGUxICYgMHgwMykgPDwgNCkgfCAoYnl0ZTIgPj4gNCk7XG4gICAgICBsZXQgb3V0Qnl0ZTMgPSAoKGJ5dGUyICYgMHgwZikgPDwgMikgfCAoYnl0ZTMgPj4gNik7XG4gICAgICBsZXQgb3V0Qnl0ZTQgPSBieXRlMyAmIDB4M2Y7XG5cbiAgICAgIGlmICghaGF2ZUJ5dGUzKSB7XG4gICAgICAgIG91dEJ5dGU0ID0gNjQ7XG5cbiAgICAgICAgaWYgKCFoYXZlQnl0ZTIpIHtcbiAgICAgICAgICBvdXRCeXRlMyA9IDY0O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG91dHB1dC5wdXNoKFxuICAgICAgICBieXRlVG9DaGFyTWFwW291dEJ5dGUxXSxcbiAgICAgICAgYnl0ZVRvQ2hhck1hcFtvdXRCeXRlMl0sXG4gICAgICAgIGJ5dGVUb0NoYXJNYXBbb3V0Qnl0ZTNdLFxuICAgICAgICBieXRlVG9DaGFyTWFwW291dEJ5dGU0XVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0LmpvaW4oJycpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBCYXNlNjQtZW5jb2RlIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcGFyYW0gaW5wdXQgQSBzdHJpbmcgdG8gZW5jb2RlLlxuICAgKiBAcGFyYW0gd2ViU2FmZSBJZiB0cnVlLCB3ZSBzaG91bGQgdXNlIHRoZVxuICAgKiAgICAgYWx0ZXJuYXRpdmUgYWxwaGFiZXQuXG4gICAqIEByZXR1cm4gVGhlIGJhc2U2NCBlbmNvZGVkIHN0cmluZy5cbiAgICovXG4gIGVuY29kZVN0cmluZyhpbnB1dDogc3RyaW5nLCB3ZWJTYWZlPzogYm9vbGVhbik6IHN0cmluZyB7XG4gICAgLy8gU2hvcnRjdXQgZm9yIE1vemlsbGEgYnJvd3NlcnMgdGhhdCBpbXBsZW1lbnRcbiAgICAvLyBhIG5hdGl2ZSBiYXNlNjQgZW5jb2RlciBpbiB0aGUgZm9ybSBvZiBcImJ0b2EvYXRvYlwiXG4gICAgaWYgKHRoaXMuSEFTX05BVElWRV9TVVBQT1JUICYmICF3ZWJTYWZlKSB7XG4gICAgICByZXR1cm4gYnRvYShpbnB1dCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVuY29kZUJ5dGVBcnJheShzdHJpbmdUb0J5dGVBcnJheShpbnB1dCksIHdlYlNhZmUpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBCYXNlNjQtZGVjb2RlIGEgc3RyaW5nLlxuICAgKlxuICAgKiBAcGFyYW0gaW5wdXQgdG8gZGVjb2RlLlxuICAgKiBAcGFyYW0gd2ViU2FmZSBUcnVlIGlmIHdlIHNob3VsZCB1c2UgdGhlXG4gICAqICAgICBhbHRlcm5hdGl2ZSBhbHBoYWJldC5cbiAgICogQHJldHVybiBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBkZWNvZGVkIHZhbHVlLlxuICAgKi9cbiAgZGVjb2RlU3RyaW5nKGlucHV0OiBzdHJpbmcsIHdlYlNhZmU6IGJvb2xlYW4pOiBzdHJpbmcge1xuICAgIC8vIFNob3J0Y3V0IGZvciBNb3ppbGxhIGJyb3dzZXJzIHRoYXQgaW1wbGVtZW50XG4gICAgLy8gYSBuYXRpdmUgYmFzZTY0IGVuY29kZXIgaW4gdGhlIGZvcm0gb2YgXCJidG9hL2F0b2JcIlxuICAgIGlmICh0aGlzLkhBU19OQVRJVkVfU1VQUE9SVCAmJiAhd2ViU2FmZSkge1xuICAgICAgcmV0dXJuIGF0b2IoaW5wdXQpO1xuICAgIH1cbiAgICByZXR1cm4gYnl0ZUFycmF5VG9TdHJpbmcodGhpcy5kZWNvZGVTdHJpbmdUb0J5dGVBcnJheShpbnB1dCwgd2ViU2FmZSkpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBCYXNlNjQtZGVjb2RlIGEgc3RyaW5nLlxuICAgKlxuICAgKiBJbiBiYXNlLTY0IGRlY29kaW5nLCBncm91cHMgb2YgZm91ciBjaGFyYWN0ZXJzIGFyZSBjb252ZXJ0ZWQgaW50byB0aHJlZVxuICAgKiBieXRlcy4gIElmIHRoZSBlbmNvZGVyIGRpZCBub3QgYXBwbHkgcGFkZGluZywgdGhlIGlucHV0IGxlbmd0aCBtYXkgbm90XG4gICAqIGJlIGEgbXVsdGlwbGUgb2YgNC5cbiAgICpcbiAgICogSW4gdGhpcyBjYXNlLCB0aGUgbGFzdCBncm91cCB3aWxsIGhhdmUgZmV3ZXIgdGhhbiA0IGNoYXJhY3RlcnMsIGFuZFxuICAgKiBwYWRkaW5nIHdpbGwgYmUgaW5mZXJyZWQuICBJZiB0aGUgZ3JvdXAgaGFzIG9uZSBvciB0d28gY2hhcmFjdGVycywgaXQgZGVjb2Rlc1xuICAgKiB0byBvbmUgYnl0ZS4gIElmIHRoZSBncm91cCBoYXMgdGhyZWUgY2hhcmFjdGVycywgaXQgZGVjb2RlcyB0byB0d28gYnl0ZXMuXG4gICAqXG4gICAqIEBwYXJhbSBpbnB1dCBJbnB1dCB0byBkZWNvZGUuXG4gICAqIEBwYXJhbSB3ZWJTYWZlIFRydWUgaWYgd2Ugc2hvdWxkIHVzZSB0aGUgd2ViLXNhZmUgYWxwaGFiZXQuXG4gICAqIEByZXR1cm4gYnl0ZXMgcmVwcmVzZW50aW5nIHRoZSBkZWNvZGVkIHZhbHVlLlxuICAgKi9cbiAgZGVjb2RlU3RyaW5nVG9CeXRlQXJyYXkoaW5wdXQ6IHN0cmluZywgd2ViU2FmZTogYm9vbGVhbik6IG51bWJlcltdIHtcbiAgICB0aGlzLmluaXRfKCk7XG5cbiAgICBjb25zdCBjaGFyVG9CeXRlTWFwID0gd2ViU2FmZVxuICAgICAgPyB0aGlzLmNoYXJUb0J5dGVNYXBXZWJTYWZlXyFcbiAgICAgIDogdGhpcy5jaGFyVG9CeXRlTWFwXyE7XG5cbiAgICBjb25zdCBvdXRwdXQ6IG51bWJlcltdID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Lmxlbmd0aDsgKSB7XG4gICAgICBjb25zdCBieXRlMSA9IGNoYXJUb0J5dGVNYXBbaW5wdXQuY2hhckF0KGkrKyldO1xuXG4gICAgICBjb25zdCBoYXZlQnl0ZTIgPSBpIDwgaW5wdXQubGVuZ3RoO1xuICAgICAgY29uc3QgYnl0ZTIgPSBoYXZlQnl0ZTIgPyBjaGFyVG9CeXRlTWFwW2lucHV0LmNoYXJBdChpKV0gOiAwO1xuICAgICAgKytpO1xuXG4gICAgICBjb25zdCBoYXZlQnl0ZTMgPSBpIDwgaW5wdXQubGVuZ3RoO1xuICAgICAgY29uc3QgYnl0ZTMgPSBoYXZlQnl0ZTMgPyBjaGFyVG9CeXRlTWFwW2lucHV0LmNoYXJBdChpKV0gOiA2NDtcbiAgICAgICsraTtcblxuICAgICAgY29uc3QgaGF2ZUJ5dGU0ID0gaSA8IGlucHV0Lmxlbmd0aDtcbiAgICAgIGNvbnN0IGJ5dGU0ID0gaGF2ZUJ5dGU0ID8gY2hhclRvQnl0ZU1hcFtpbnB1dC5jaGFyQXQoaSldIDogNjQ7XG4gICAgICArK2k7XG5cbiAgICAgIGlmIChieXRlMSA9PSBudWxsIHx8IGJ5dGUyID09IG51bGwgfHwgYnl0ZTMgPT0gbnVsbCB8fCBieXRlNCA9PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBEZWNvZGVCYXNlNjRTdHJpbmdFcnJvcigpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvdXRCeXRlMSA9IChieXRlMSA8PCAyKSB8IChieXRlMiA+PiA0KTtcbiAgICAgIG91dHB1dC5wdXNoKG91dEJ5dGUxKTtcblxuICAgICAgaWYgKGJ5dGUzICE9PSA2NCkge1xuICAgICAgICBjb25zdCBvdXRCeXRlMiA9ICgoYnl0ZTIgPDwgNCkgJiAweGYwKSB8IChieXRlMyA+PiAyKTtcbiAgICAgICAgb3V0cHV0LnB1c2gob3V0Qnl0ZTIpO1xuXG4gICAgICAgIGlmIChieXRlNCAhPT0gNjQpIHtcbiAgICAgICAgICBjb25zdCBvdXRCeXRlMyA9ICgoYnl0ZTMgPDwgNikgJiAweGMwKSB8IGJ5dGU0O1xuICAgICAgICAgIG91dHB1dC5wdXNoKG91dEJ5dGUzKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH0sXG5cbiAgLyoqXG4gICAqIExhenkgc3RhdGljIGluaXRpYWxpemF0aW9uIGZ1bmN0aW9uLiBDYWxsZWQgYmVmb3JlXG4gICAqIGFjY2Vzc2luZyBhbnkgb2YgdGhlIHN0YXRpYyBtYXAgdmFyaWFibGVzLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgaW5pdF8oKSB7XG4gICAgaWYgKCF0aGlzLmJ5dGVUb0NoYXJNYXBfKSB7XG4gICAgICB0aGlzLmJ5dGVUb0NoYXJNYXBfID0ge307XG4gICAgICB0aGlzLmNoYXJUb0J5dGVNYXBfID0ge307XG4gICAgICB0aGlzLmJ5dGVUb0NoYXJNYXBXZWJTYWZlXyA9IHt9O1xuICAgICAgdGhpcy5jaGFyVG9CeXRlTWFwV2ViU2FmZV8gPSB7fTtcblxuICAgICAgLy8gV2Ugd2FudCBxdWljayBtYXBwaW5ncyBiYWNrIGFuZCBmb3J0aCwgc28gd2UgcHJlY29tcHV0ZSB0d28gbWFwcy5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5FTkNPREVEX1ZBTFMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5ieXRlVG9DaGFyTWFwX1tpXSA9IHRoaXMuRU5DT0RFRF9WQUxTLmNoYXJBdChpKTtcbiAgICAgICAgdGhpcy5jaGFyVG9CeXRlTWFwX1t0aGlzLmJ5dGVUb0NoYXJNYXBfW2ldXSA9IGk7XG4gICAgICAgIHRoaXMuYnl0ZVRvQ2hhck1hcFdlYlNhZmVfW2ldID0gdGhpcy5FTkNPREVEX1ZBTFNfV0VCU0FGRS5jaGFyQXQoaSk7XG4gICAgICAgIHRoaXMuY2hhclRvQnl0ZU1hcFdlYlNhZmVfW3RoaXMuYnl0ZVRvQ2hhck1hcFdlYlNhZmVfW2ldXSA9IGk7XG5cbiAgICAgICAgLy8gQmUgZm9yZ2l2aW5nIHdoZW4gZGVjb2RpbmcgYW5kIGNvcnJlY3RseSBkZWNvZGUgYm90aCBlbmNvZGluZ3MuXG4gICAgICAgIGlmIChpID49IHRoaXMuRU5DT0RFRF9WQUxTX0JBU0UubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy5jaGFyVG9CeXRlTWFwX1t0aGlzLkVOQ09ERURfVkFMU19XRUJTQUZFLmNoYXJBdChpKV0gPSBpO1xuICAgICAgICAgIHRoaXMuY2hhclRvQnl0ZU1hcFdlYlNhZmVfW3RoaXMuRU5DT0RFRF9WQUxTLmNoYXJBdChpKV0gPSBpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEFuIGVycm9yIGVuY291bnRlcmVkIHdoaWxlIGRlY29kaW5nIGJhc2U2NCBzdHJpbmcuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZWNvZGVCYXNlNjRTdHJpbmdFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgcmVhZG9ubHkgbmFtZSA9ICdEZWNvZGVCYXNlNjRTdHJpbmdFcnJvcic7XG59XG5cbi8qKlxuICogVVJMLXNhZmUgYmFzZTY0IGVuY29kaW5nXG4gKi9cbmV4cG9ydCBjb25zdCBiYXNlNjRFbmNvZGUgPSBmdW5jdGlvbiAoc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB1dGY4Qnl0ZXMgPSBzdHJpbmdUb0J5dGVBcnJheShzdHIpO1xuICByZXR1cm4gYmFzZTY0LmVuY29kZUJ5dGVBcnJheSh1dGY4Qnl0ZXMsIHRydWUpO1xufTtcblxuLyoqXG4gKiBVUkwtc2FmZSBiYXNlNjQgZW5jb2RpbmcgKHdpdGhvdXQgXCIuXCIgcGFkZGluZyBpbiB0aGUgZW5kKS5cbiAqIGUuZy4gVXNlZCBpbiBKU09OIFdlYiBUb2tlbiAoSldUKSBwYXJ0cy5cbiAqL1xuZXhwb3J0IGNvbnN0IGJhc2U2NHVybEVuY29kZVdpdGhvdXRQYWRkaW5nID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gVXNlIGJhc2U2NHVybCBlbmNvZGluZyBhbmQgcmVtb3ZlIHBhZGRpbmcgaW4gdGhlIGVuZCAoZG90IGNoYXJhY3RlcnMpLlxuICByZXR1cm4gYmFzZTY0RW5jb2RlKHN0cikucmVwbGFjZSgvXFwuL2csICcnKTtcbn07XG5cbi8qKlxuICogVVJMLXNhZmUgYmFzZTY0IGRlY29kaW5nXG4gKlxuICogTk9URTogRE8gTk9UIHVzZSB0aGUgZ2xvYmFsIGF0b2IoKSBmdW5jdGlvbiAtIGl0IGRvZXMgTk9UIHN1cHBvcnQgdGhlXG4gKiBiYXNlNjRVcmwgdmFyaWFudCBlbmNvZGluZy5cbiAqXG4gKiBAcGFyYW0gc3RyIFRvIGJlIGRlY29kZWRcbiAqIEByZXR1cm4gRGVjb2RlZCByZXN1bHQsIGlmIHBvc3NpYmxlXG4gKi9cbmV4cG9ydCBjb25zdCBiYXNlNjREZWNvZGUgPSBmdW5jdGlvbiAoc3RyOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYmFzZTY0LmRlY29kZVN0cmluZyhzdHIsIHRydWUpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc29sZS5lcnJvcignYmFzZTY0RGVjb2RlIGZhaWxlZDogJywgZSk7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogRG8gYSBkZWVwLWNvcHkgb2YgYmFzaWMgSmF2YVNjcmlwdCBPYmplY3RzIG9yIEFycmF5cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBDb3B5PFQ+KHZhbHVlOiBUKTogVCB7XG4gIHJldHVybiBkZWVwRXh0ZW5kKHVuZGVmaW5lZCwgdmFsdWUpIGFzIFQ7XG59XG5cbi8qKlxuICogQ29weSBwcm9wZXJ0aWVzIGZyb20gc291cmNlIHRvIHRhcmdldCAocmVjdXJzaXZlbHkgYWxsb3dzIGV4dGVuc2lvblxuICogb2YgT2JqZWN0cyBhbmQgQXJyYXlzKS4gIFNjYWxhciB2YWx1ZXMgaW4gdGhlIHRhcmdldCBhcmUgb3Zlci13cml0dGVuLlxuICogSWYgdGFyZ2V0IGlzIHVuZGVmaW5lZCwgYW4gb2JqZWN0IG9mIHRoZSBhcHByb3ByaWF0ZSB0eXBlIHdpbGwgYmUgY3JlYXRlZFxuICogKGFuZCByZXR1cm5lZCkuXG4gKlxuICogV2UgcmVjdXJzaXZlbHkgY29weSBhbGwgY2hpbGQgcHJvcGVydGllcyBvZiBwbGFpbiBPYmplY3RzIGluIHRoZSBzb3VyY2UtIHNvXG4gKiB0aGF0IG5hbWVzcGFjZS0gbGlrZSBkaWN0aW9uYXJpZXMgYXJlIG1lcmdlZC5cbiAqXG4gKiBOb3RlIHRoYXQgdGhlIHRhcmdldCBjYW4gYmUgYSBmdW5jdGlvbiwgaW4gd2hpY2ggY2FzZSB0aGUgcHJvcGVydGllcyBpblxuICogdGhlIHNvdXJjZSBPYmplY3QgYXJlIGNvcGllZCBvbnRvIGl0IGFzIHN0YXRpYyBwcm9wZXJ0aWVzIG9mIHRoZSBGdW5jdGlvbi5cbiAqXG4gKiBOb3RlOiB3ZSBkb24ndCBtZXJnZSBfX3Byb3RvX18gdG8gcHJldmVudCBwcm90b3R5cGUgcG9sbHV0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWVwRXh0ZW5kKHRhcmdldDogdW5rbm93biwgc291cmNlOiB1bmtub3duKTogdW5rbm93biB7XG4gIGlmICghKHNvdXJjZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICByZXR1cm4gc291cmNlO1xuICB9XG5cbiAgc3dpdGNoIChzb3VyY2UuY29uc3RydWN0b3IpIHtcbiAgICBjYXNlIERhdGU6XG4gICAgICAvLyBUcmVhdCBEYXRlcyBsaWtlIHNjYWxhcnM7IGlmIHRoZSB0YXJnZXQgZGF0ZSBvYmplY3QgaGFkIGFueSBjaGlsZFxuICAgICAgLy8gcHJvcGVydGllcyAtIHRoZXkgd2lsbCBiZSBsb3N0IVxuICAgICAgY29uc3QgZGF0ZVZhbHVlID0gc291cmNlIGFzIERhdGU7XG4gICAgICByZXR1cm4gbmV3IERhdGUoZGF0ZVZhbHVlLmdldFRpbWUoKSk7XG5cbiAgICBjYXNlIE9iamVjdDpcbiAgICAgIGlmICh0YXJnZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0YXJnZXQgPSB7fTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQXJyYXk6XG4gICAgICAvLyBBbHdheXMgY29weSB0aGUgYXJyYXkgc291cmNlIGFuZCBvdmVyd3JpdGUgdGhlIHRhcmdldC5cbiAgICAgIHRhcmdldCA9IFtdO1xuICAgICAgYnJlYWs7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgLy8gTm90IGEgcGxhaW4gT2JqZWN0IC0gdHJlYXQgaXQgYXMgYSBzY2FsYXIuXG4gICAgICByZXR1cm4gc291cmNlO1xuICB9XG5cbiAgZm9yIChjb25zdCBwcm9wIGluIHNvdXJjZSkge1xuICAgIC8vIHVzZSBpc1ZhbGlkS2V5IHRvIGd1YXJkIGFnYWluc3QgcHJvdG90eXBlIHBvbGx1dGlvbi4gU2VlIGh0dHBzOi8vc255ay5pby92dWxuL1NOWUstSlMtTE9EQVNILTQ1MDIwMlxuICAgIGlmICghc291cmNlLmhhc093blByb3BlcnR5KHByb3ApIHx8ICFpc1ZhbGlkS2V5KHByb3ApKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgKHRhcmdldCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbcHJvcF0gPSBkZWVwRXh0ZW5kKFxuICAgICAgKHRhcmdldCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbcHJvcF0sXG4gICAgICAoc291cmNlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtwcm9wXVxuICAgICk7XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuXG5mdW5jdGlvbiBpc1ZhbGlkS2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBrZXkgIT09ICdfX3Byb3RvX18nO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIyIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogUG9seWZpbGwgZm9yIGBnbG9iYWxUaGlzYCBvYmplY3QuXG4gKiBAcmV0dXJucyB0aGUgYGdsb2JhbFRoaXNgIG9iamVjdCBmb3IgdGhlIGdpdmVuIGVudmlyb25tZW50LlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2xvYmFsKCk6IHR5cGVvZiBnbG9iYWxUaGlzIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9XG4gIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH1cbiAgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBsb2NhdGUgZ2xvYmFsIG9iamVjdC4nKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBiYXNlNjREZWNvZGUgfSBmcm9tICcuL2NyeXB0JztcbmltcG9ydCB7IGdldEdsb2JhbCB9IGZyb20gJy4vZ2xvYmFsJztcbmltcG9ydCB7IGdldERlZmF1bHRzRnJvbVBvc3RpbnN0YWxsIH0gZnJvbSAnLi9wb3N0aW5zdGFsbCc7XG5cbi8qKlxuICogS2V5cyBmb3IgZXhwZXJpbWVudGFsIHByb3BlcnRpZXMgb24gdGhlIGBGaXJlYmFzZURlZmF1bHRzYCBvYmplY3QuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCB0eXBlIEV4cGVyaW1lbnRhbEtleSA9ICdhdXRoVG9rZW5TeW5jVVJMJyB8ICdhdXRoSWRUb2tlbk1heEFnZSc7XG5cbi8qKlxuICogQW4gb2JqZWN0IHRoYXQgY2FuIGJlIGluamVjdGVkIGludG8gdGhlIGVudmlyb25tZW50IGFzIF9fRklSRUJBU0VfREVGQVVMVFNfXyxcbiAqIGVpdGhlciBhcyBhIHByb3BlcnR5IG9mIGdsb2JhbFRoaXMsIGEgc2hlbGwgZW52aXJvbm1lbnQgdmFyaWFibGUsIG9yIGFcbiAqIGNvb2tpZS5cbiAqXG4gKiBUaGlzIG9iamVjdCBjYW4gYmUgdXNlZCB0byBhdXRvbWF0aWNhbGx5IGNvbmZpZ3VyZSBhbmQgaW5pdGlhbGl6ZVxuICogYSBGaXJlYmFzZSBhcHAgYXMgd2VsbCBhcyBhbnkgZW11bGF0b3JzLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBGaXJlYmFzZURlZmF1bHRzIHtcbiAgY29uZmlnPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgZW11bGF0b3JIb3N0cz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIF9hdXRoVG9rZW5TeW5jVVJMPzogc3RyaW5nO1xuICBfYXV0aElkVG9rZW5NYXhBZ2U/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBPdmVycmlkZSBGaXJlYmFzZSdzIHJ1bnRpbWUgZW52aXJvbm1lbnQgZGV0ZWN0aW9uIGFuZFxuICAgKiBmb3JjZSB0aGUgU0RLIHRvIGFjdCBhcyBpZiBpdCB3ZXJlIGluIHRoZSBzcGVjaWZpZWQgZW52aXJvbm1lbnQuXG4gICAqL1xuICBmb3JjZUVudmlyb25tZW50PzogJ2Jyb3dzZXInIHwgJ25vZGUnO1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufVxuXG5kZWNsYXJlIGdsb2JhbCB7XG4gIC8vIE5lZWQgYHZhcmAgZm9yIHRoaXMgdG8gd29yay5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXZhclxuICB2YXIgX19GSVJFQkFTRV9ERUZBVUxUU19fOiBGaXJlYmFzZURlZmF1bHRzIHwgdW5kZWZpbmVkO1xufVxuXG5jb25zdCBnZXREZWZhdWx0c0Zyb21HbG9iYWwgPSAoKTogRmlyZWJhc2VEZWZhdWx0cyB8IHVuZGVmaW5lZCA9PlxuICBnZXRHbG9iYWwoKS5fX0ZJUkVCQVNFX0RFRkFVTFRTX187XG5cbi8qKlxuICogQXR0ZW1wdCB0byByZWFkIGRlZmF1bHRzIGZyb20gYSBKU09OIHN0cmluZyBwcm92aWRlZCB0b1xuICogcHJvY2VzcyguKWVudiguKV9fRklSRUJBU0VfREVGQVVMVFNfXyBvciBhIEpTT04gZmlsZSB3aG9zZSBwYXRoIGlzIGluXG4gKiBwcm9jZXNzKC4pZW52KC4pX19GSVJFQkFTRV9ERUZBVUxUU19QQVRIX19cbiAqIFRoZSBkb3RzIGFyZSBpbiBwYXJlbnMgYmVjYXVzZSBjZXJ0YWluIGNvbXBpbGVycyAoVml0ZT8pIGNhbm5vdFxuICogaGFuZGxlIHNlZWluZyB0aGF0IHZhcmlhYmxlIGluIGNvbW1lbnRzLlxuICogU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9maXJlYmFzZS9maXJlYmFzZS1qcy1zZGsvaXNzdWVzLzY4MzhcbiAqL1xuY29uc3QgZ2V0RGVmYXVsdHNGcm9tRW52VmFyaWFibGUgPSAoKTogRmlyZWJhc2VEZWZhdWx0cyB8IHVuZGVmaW5lZCA9PiB7XG4gIGlmICh0eXBlb2YgcHJvY2VzcyA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIHByb2Nlc3MuZW52ID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBkZWZhdWx0c0pzb25TdHJpbmcgPSBwcm9jZXNzLmVudi5fX0ZJUkVCQVNFX0RFRkFVTFRTX187XG4gIGlmIChkZWZhdWx0c0pzb25TdHJpbmcpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShkZWZhdWx0c0pzb25TdHJpbmcpO1xuICB9XG59O1xuXG5jb25zdCBnZXREZWZhdWx0c0Zyb21Db29raWUgPSAoKTogRmlyZWJhc2VEZWZhdWx0cyB8IHVuZGVmaW5lZCA9PiB7XG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGxldCBtYXRjaDtcbiAgdHJ5IHtcbiAgICBtYXRjaCA9IGRvY3VtZW50LmNvb2tpZS5tYXRjaCgvX19GSVJFQkFTRV9ERUZBVUxUU19fPShbXjtdKykvKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIFNvbWUgZW52aXJvbm1lbnRzIHN1Y2ggYXMgQW5ndWxhciBVbml2ZXJzYWwgU1NSIGhhdmUgYVxuICAgIC8vIGBkb2N1bWVudGAgb2JqZWN0IGJ1dCBlcnJvciBvbiBhY2Nlc3NpbmcgYGRvY3VtZW50LmNvb2tpZWAuXG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IGRlY29kZWQgPSBtYXRjaCAmJiBiYXNlNjREZWNvZGUobWF0Y2hbMV0pO1xuICByZXR1cm4gZGVjb2RlZCAmJiBKU09OLnBhcnNlKGRlY29kZWQpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIF9fRklSRUJBU0VfREVGQVVMVFNfXyBvYmplY3QuIEl0IGNoZWNrcyBpbiBvcmRlcjpcbiAqICgxKSBpZiBzdWNoIGFuIG9iamVjdCBleGlzdHMgYXMgYSBwcm9wZXJ0eSBvZiBgZ2xvYmFsVGhpc2BcbiAqICgyKSBpZiBzdWNoIGFuIG9iamVjdCB3YXMgcHJvdmlkZWQgb24gYSBzaGVsbCBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICogKDMpIGlmIHN1Y2ggYW4gb2JqZWN0IGV4aXN0cyBpbiBhIGNvb2tpZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZ2V0RGVmYXVsdHMgPSAoKTogRmlyZWJhc2VEZWZhdWx0cyB8IHVuZGVmaW5lZCA9PiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIChcbiAgICAgIGdldERlZmF1bHRzRnJvbVBvc3RpbnN0YWxsKCkgfHxcbiAgICAgIGdldERlZmF1bHRzRnJvbUdsb2JhbCgpIHx8XG4gICAgICBnZXREZWZhdWx0c0Zyb21FbnZWYXJpYWJsZSgpIHx8XG4gICAgICBnZXREZWZhdWx0c0Zyb21Db29raWUoKVxuICAgICk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvKipcbiAgICAgKiBDYXRjaC1hbGwgZm9yIGJlaW5nIHVuYWJsZSB0byBnZXQgX19GSVJFQkFTRV9ERUZBVUxUU19fIGR1ZVxuICAgICAqIHRvIGFueSBlbnZpcm9ubWVudCBjYXNlIHdlIGhhdmUgbm90IGFjY291bnRlZCBmb3IuIExvZyB0b1xuICAgICAqIGluZm8gaW5zdGVhZCBvZiBzd2FsbG93aW5nIHNvIHdlIGNhbiBmaW5kIHRoZXNlIHVua25vd24gY2FzZXNcbiAgICAgKiBhbmQgYWRkIHBhdGhzIGZvciB0aGVtIGlmIG5lZWRlZC5cbiAgICAgKi9cbiAgICBjb25zb2xlLmluZm8oYFVuYWJsZSB0byBnZXQgX19GSVJFQkFTRV9ERUZBVUxUU19fIGR1ZSB0bzogJHtlfWApO1xuICAgIHJldHVybjtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXR1cm5zIGVtdWxhdG9yIGhvc3Qgc3RvcmVkIGluIHRoZSBfX0ZJUkVCQVNFX0RFRkFVTFRTX18gb2JqZWN0XG4gKiBmb3IgdGhlIGdpdmVuIHByb2R1Y3QuXG4gKiBAcmV0dXJucyBhIFVSTCBob3N0IGZvcm1hdHRlZCBsaWtlIGAxMjcuMC4wLjE6OTk5OWAgb3IgYFs6OjFdOjQwMDBgIGlmIGF2YWlsYWJsZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdCA9IChcbiAgcHJvZHVjdE5hbWU6IHN0cmluZ1xuKTogc3RyaW5nIHwgdW5kZWZpbmVkID0+IGdldERlZmF1bHRzKCk/LmVtdWxhdG9ySG9zdHM/Lltwcm9kdWN0TmFtZV07XG5cbi8qKlxuICogUmV0dXJucyBlbXVsYXRvciBob3N0bmFtZSBhbmQgcG9ydCBzdG9yZWQgaW4gdGhlIF9fRklSRUJBU0VfREVGQVVMVFNfXyBvYmplY3RcbiAqIGZvciB0aGUgZ2l2ZW4gcHJvZHVjdC5cbiAqIEByZXR1cm5zIGEgcGFpciBvZiBob3N0bmFtZSBhbmQgcG9ydCBsaWtlIGBbXCI6OjFcIiwgNDAwMF1gIGlmIGF2YWlsYWJsZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdG5hbWVBbmRQb3J0ID0gKFxuICBwcm9kdWN0TmFtZTogc3RyaW5nXG4pOiBbaG9zdG5hbWU6IHN0cmluZywgcG9ydDogbnVtYmVyXSB8IHVuZGVmaW5lZCA9PiB7XG4gIGNvbnN0IGhvc3QgPSBnZXREZWZhdWx0RW11bGF0b3JIb3N0KHByb2R1Y3ROYW1lKTtcbiAgaWYgKCFob3N0KSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCBzZXBhcmF0b3JJbmRleCA9IGhvc3QubGFzdEluZGV4T2YoJzonKTsgLy8gRmluZGluZyB0aGUgbGFzdCBzaW5jZSBJUHY2IGFkZHIgYWxzbyBoYXMgY29sb25zLlxuICBpZiAoc2VwYXJhdG9ySW5kZXggPD0gMCB8fCBzZXBhcmF0b3JJbmRleCArIDEgPT09IGhvc3QubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGhvc3QgJHtob3N0fSB3aXRoIG5vIHNlcGFyYXRlIGhvc3RuYW1lIGFuZCBwb3J0IWApO1xuICB9XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLWdsb2JhbHNcbiAgY29uc3QgcG9ydCA9IHBhcnNlSW50KGhvc3Quc3Vic3RyaW5nKHNlcGFyYXRvckluZGV4ICsgMSksIDEwKTtcbiAgaWYgKGhvc3RbMF0gPT09ICdbJykge1xuICAgIC8vIEJyYWNrZXQtcXVvdGVkIGBbaXB2NmFkZHJdOnBvcnRgID0+IHJldHVybiBcImlwdjZhZGRyXCIgKHdpdGhvdXQgYnJhY2tldHMpLlxuICAgIHJldHVybiBbaG9zdC5zdWJzdHJpbmcoMSwgc2VwYXJhdG9ySW5kZXggLSAxKSwgcG9ydF07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFtob3N0LnN1YnN0cmluZygwLCBzZXBhcmF0b3JJbmRleCksIHBvcnRdO1xuICB9XG59O1xuXG4vKipcbiAqIFJldHVybnMgRmlyZWJhc2UgYXBwIGNvbmZpZyBzdG9yZWQgaW4gdGhlIF9fRklSRUJBU0VfREVGQVVMVFNfXyBvYmplY3QuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBnZXREZWZhdWx0QXBwQ29uZmlnID0gKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCB1bmRlZmluZWQgPT5cbiAgZ2V0RGVmYXVsdHMoKT8uY29uZmlnO1xuXG4vKipcbiAqIFJldHVybnMgYW4gZXhwZXJpbWVudGFsIHNldHRpbmcgb24gdGhlIF9fRklSRUJBU0VfREVGQVVMVFNfXyBvYmplY3QgKHByb3BlcnRpZXNcbiAqIHByZWZpeGVkIGJ5IFwiX1wiKVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZ2V0RXhwZXJpbWVudGFsU2V0dGluZyA9IDxUIGV4dGVuZHMgRXhwZXJpbWVudGFsS2V5PihcbiAgbmFtZTogVFxuKTogRmlyZWJhc2VEZWZhdWx0c1tgXyR7VH1gXSA9PlxuICBnZXREZWZhdWx0cygpPy5bYF8ke25hbWV9YF0gYXMgRmlyZWJhc2VEZWZhdWx0c1tgXyR7VH1gXTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgY2xhc3MgRGVmZXJyZWQ8Uj4ge1xuICBwcm9taXNlOiBQcm9taXNlPFI+O1xuICByZWplY3Q6ICh2YWx1ZT86IHVua25vd24pID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgcmVzb2x2ZTogKHZhbHVlPzogdW5rbm93bikgPT4gdm9pZCA9ICgpID0+IHt9O1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnJlc29sdmUgPSByZXNvbHZlIGFzICh2YWx1ZT86IHVua25vd24pID0+IHZvaWQ7XG4gICAgICB0aGlzLnJlamVjdCA9IHJlamVjdCBhcyAodmFsdWU/OiB1bmtub3duKSA9PiB2b2lkO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE91ciBBUEkgaW50ZXJuYWxzIGFyZSBub3QgcHJvbWlzaWZpZWQgYW5kIGNhbm5vdCBiZWNhdXNlIG91ciBjYWxsYmFjayBBUElzIGhhdmUgc3VidGxlIGV4cGVjdGF0aW9ucyBhcm91bmRcbiAgICogaW52b2tpbmcgcHJvbWlzZXMgaW5saW5lLCB3aGljaCBQcm9taXNlcyBhcmUgZm9yYmlkZGVuIHRvIGRvLiBUaGlzIG1ldGhvZCBhY2NlcHRzIGFuIG9wdGlvbmFsIG5vZGUtc3R5bGUgY2FsbGJhY2tcbiAgICogYW5kIHJldHVybnMgYSBub2RlLXN0eWxlIGNhbGxiYWNrIHdoaWNoIHdpbGwgcmVzb2x2ZSBvciByZWplY3QgdGhlIERlZmVycmVkJ3MgcHJvbWlzZS5cbiAgICovXG4gIHdyYXBDYWxsYmFjayhcbiAgICBjYWxsYmFjaz86IChlcnJvcj86IHVua25vd24sIHZhbHVlPzogdW5rbm93bikgPT4gdm9pZFxuICApOiAoZXJyb3I6IHVua25vd24sIHZhbHVlPzogdW5rbm93bikgPT4gdm9pZCB7XG4gICAgcmV0dXJuIChlcnJvciwgdmFsdWU/KSA9PiB7XG4gICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5yZWplY3QoZXJyb3IpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5yZXNvbHZlKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgLy8gQXR0YWNoaW5nIG5vb3AgaGFuZGxlciBqdXN0IGluIGNhc2UgZGV2ZWxvcGVyIHdhc24ndCBleHBlY3RpbmdcbiAgICAgICAgLy8gcHJvbWlzZXNcbiAgICAgICAgdGhpcy5wcm9taXNlLmNhdGNoKCgpID0+IHt9KTtcblxuICAgICAgICAvLyBTb21lIG9mIG91ciBjYWxsYmFja3MgZG9uJ3QgZXhwZWN0IGEgdmFsdWUgYW5kIG91ciBvd24gdGVzdHNcbiAgICAgICAgLy8gYXNzZXJ0IHRoYXQgdGhlIHBhcmFtZXRlciBsZW5ndGggaXMgMVxuICAgICAgICBpZiAoY2FsbGJhY2subGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgY2FsbGJhY2soZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjUgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBob3N0IGlzIGEgY2xvdWQgd29ya3N0YXRpb24gb3Igbm90LlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDbG91ZFdvcmtzdGF0aW9uKHVybDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIC8vIGBpc0Nsb3VkV29ya3N0YXRpb25gIGlzIGNhbGxlZCB3aXRob3V0IHByb3RvY29sIGluIGNlcnRhaW4gY29ubmVjdCpFbXVsYXRvciBmdW5jdGlvbnNcbiAgLy8gSW4gSFRUUCByZXF1ZXN0IGJ1aWxkZXJzLCBpdCdzIGNhbGxlZCB3aXRoIHRoZSBwcm90b2NvbC5cbiAgLy8gSWYgY2FsbGVkIHdpdGggcHJvdG9jb2wgcHJlZml4LCBpdCdzIGEgdmFsaWQgVVJMLCBzbyB3ZSBleHRyYWN0IHRoZSBob3N0bmFtZVxuICAvLyBJZiBjYWxsZWQgd2l0aG91dCwgd2UgYXNzdW1lIHRoZSBzdHJpbmcgaXMgdGhlIGhvc3RuYW1lLlxuICB0cnkge1xuICAgIGNvbnN0IGhvc3QgPVxuICAgICAgdXJsLnN0YXJ0c1dpdGgoJ2h0dHA6Ly8nKSB8fCB1cmwuc3RhcnRzV2l0aCgnaHR0cHM6Ly8nKVxuICAgICAgICA/IG5ldyBVUkwodXJsKS5ob3N0bmFtZVxuICAgICAgICA6IHVybDtcbiAgICByZXR1cm4gaG9zdC5lbmRzV2l0aCgnLmNsb3Vkd29ya3N0YXRpb25zLmRldicpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBNYWtlcyBhIGZldGNoIHJlcXVlc3QgdG8gdGhlIGdpdmVuIHNlcnZlci5cbiAqIE1vc3RseSB1c2VkIGZvciBmb3J3YXJkaW5nIGNvb2tpZXMgaW4gRmlyZWJhc2UgU3R1ZGlvLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcGluZ1NlcnZlcihlbmRwb2ludDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZldGNoKGVuZHBvaW50LCB7XG4gICAgY3JlZGVudGlhbHM6ICdpbmNsdWRlJ1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdC5vaztcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBiYXNlNjR1cmxFbmNvZGVXaXRob3V0UGFkZGluZyB9IGZyb20gJy4vY3J5cHQnO1xuaW1wb3J0IHsgaXNDbG91ZFdvcmtzdGF0aW9uIH0gZnJvbSAnLi91cmwnO1xuXG4vLyBGaXJlYmFzZSBBdXRoIHRva2VucyBjb250YWluIHNuYWtlX2Nhc2UgY2xhaW1zIGZvbGxvd2luZyB0aGUgSldUIHN0YW5kYXJkIC8gY29udmVudGlvbi5cbi8qIGVzbGludC1kaXNhYmxlIGNhbWVsY2FzZSAqL1xuXG5leHBvcnQgdHlwZSBGaXJlYmFzZVNpZ25JblByb3ZpZGVyID1cbiAgfCAnY3VzdG9tJ1xuICB8ICdlbWFpbCdcbiAgfCAncGFzc3dvcmQnXG4gIHwgJ3Bob25lJ1xuICB8ICdhbm9ueW1vdXMnXG4gIHwgJ2dvb2dsZS5jb20nXG4gIHwgJ2ZhY2Vib29rLmNvbSdcbiAgfCAnZ2l0aHViLmNvbSdcbiAgfCAndHdpdHRlci5jb20nXG4gIHwgJ21pY3Jvc29mdC5jb20nXG4gIHwgJ2FwcGxlLmNvbSc7XG5cbmludGVyZmFjZSBGaXJlYmFzZUlkVG9rZW4ge1xuICAvLyBBbHdheXMgc2V0IHRvIGh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9QUk9KRUNUX0lEXG4gIGlzczogc3RyaW5nO1xuXG4gIC8vIEFsd2F5cyBzZXQgdG8gUFJPSkVDVF9JRFxuICBhdWQ6IHN0cmluZztcblxuICAvLyBUaGUgdXNlcidzIHVuaXF1ZSBJRFxuICBzdWI6IHN0cmluZztcblxuICAvLyBUaGUgdG9rZW4gaXNzdWUgdGltZSwgaW4gc2Vjb25kcyBzaW5jZSBlcG9jaFxuICBpYXQ6IG51bWJlcjtcblxuICAvLyBUaGUgdG9rZW4gZXhwaXJ5IHRpbWUsIG5vcm1hbGx5ICdpYXQnICsgMzYwMFxuICBleHA6IG51bWJlcjtcblxuICAvLyBUaGUgdXNlcidzIHVuaXF1ZSBJRC4gTXVzdCBiZSBlcXVhbCB0byAnc3ViJ1xuICB1c2VyX2lkOiBzdHJpbmc7XG5cbiAgLy8gVGhlIHRpbWUgdGhlIHVzZXIgYXV0aGVudGljYXRlZCwgbm9ybWFsbHkgJ2lhdCdcbiAgYXV0aF90aW1lOiBudW1iZXI7XG5cbiAgLy8gVGhlIHNpZ24gaW4gcHJvdmlkZXIsIG9ubHkgc2V0IHdoZW4gdGhlIHByb3ZpZGVyIGlzICdhbm9ueW1vdXMnXG4gIHByb3ZpZGVyX2lkPzogJ2Fub255bW91cyc7XG5cbiAgLy8gVGhlIHVzZXIncyBwcmltYXJ5IGVtYWlsXG4gIGVtYWlsPzogc3RyaW5nO1xuXG4gIC8vIFRoZSB1c2VyJ3MgZW1haWwgdmVyaWZpY2F0aW9uIHN0YXR1c1xuICBlbWFpbF92ZXJpZmllZD86IGJvb2xlYW47XG5cbiAgLy8gVGhlIHVzZXIncyBwcmltYXJ5IHBob25lIG51bWJlclxuICBwaG9uZV9udW1iZXI/OiBzdHJpbmc7XG5cbiAgLy8gVGhlIHVzZXIncyBkaXNwbGF5IG5hbWVcbiAgbmFtZT86IHN0cmluZztcblxuICAvLyBUaGUgdXNlcidzIHByb2ZpbGUgcGhvdG8gVVJMXG4gIHBpY3R1cmU/OiBzdHJpbmc7XG5cbiAgLy8gSW5mb3JtYXRpb24gb24gYWxsIGlkZW50aXRpZXMgbGlua2VkIHRvIHRoaXMgdXNlclxuICBmaXJlYmFzZToge1xuICAgIC8vIFRoZSBwcmltYXJ5IHNpZ24taW4gcHJvdmlkZXJcbiAgICBzaWduX2luX3Byb3ZpZGVyOiBGaXJlYmFzZVNpZ25JblByb3ZpZGVyO1xuXG4gICAgLy8gQSBtYXAgb2YgcHJvdmlkZXJzIHRvIHRoZSB1c2VyJ3MgbGlzdCBvZiB1bmlxdWUgaWRlbnRpZmllcnMgZnJvbVxuICAgIC8vIGVhY2ggcHJvdmlkZXJcbiAgICBpZGVudGl0aWVzPzogeyBbcHJvdmlkZXIgaW4gRmlyZWJhc2VTaWduSW5Qcm92aWRlcl0/OiBzdHJpbmdbXSB9O1xuICB9O1xuXG4gIC8vIEN1c3RvbSBjbGFpbXMgc2V0IGJ5IHRoZSBkZXZlbG9wZXJcbiAgW2NsYWltOiBzdHJpbmddOiB1bmtub3duO1xuXG4gIHVpZD86IG5ldmVyOyAvLyBUcnkgdG8gY2F0Y2ggYSBjb21tb24gbWlzdGFrZSBvZiBcInVpZFwiIChzaG91bGQgYmUgXCJzdWJcIiBpbnN0ZWFkKS5cbn1cblxuZXhwb3J0IHR5cGUgRW11bGF0b3JNb2NrVG9rZW5PcHRpb25zID0gKHsgdXNlcl9pZDogc3RyaW5nIH0gfCB7IHN1Yjogc3RyaW5nIH0pICZcbiAgUGFydGlhbDxGaXJlYmFzZUlkVG9rZW4+O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTW9ja1VzZXJUb2tlbihcbiAgdG9rZW46IEVtdWxhdG9yTW9ja1Rva2VuT3B0aW9ucyxcbiAgcHJvamVjdElkPzogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBpZiAodG9rZW4udWlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ1RoZSBcInVpZFwiIGZpZWxkIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQgYnkgbW9ja1VzZXJUb2tlbi4gUGxlYXNlIHVzZSBcInN1YlwiIGluc3RlYWQgZm9yIEZpcmViYXNlIEF1dGggVXNlciBJRC4nXG4gICAgKTtcbiAgfVxuICAvLyBVbnNlY3VyZWQgSldUcyB1c2UgXCJub25lXCIgYXMgdGhlIGFsZ29yaXRobS5cbiAgY29uc3QgaGVhZGVyID0ge1xuICAgIGFsZzogJ25vbmUnLFxuICAgIHR5cGU6ICdKV1QnXG4gIH07XG5cbiAgY29uc3QgcHJvamVjdCA9IHByb2plY3RJZCB8fCAnZGVtby1wcm9qZWN0JztcbiAgY29uc3QgaWF0ID0gdG9rZW4uaWF0IHx8IDA7XG4gIGNvbnN0IHN1YiA9IHRva2VuLnN1YiB8fCB0b2tlbi51c2VyX2lkO1xuICBpZiAoIXN1Yikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm1vY2tVc2VyVG9rZW4gbXVzdCBjb250YWluICdzdWInIG9yICd1c2VyX2lkJyBmaWVsZCFcIik7XG4gIH1cblxuICBjb25zdCBwYXlsb2FkOiBGaXJlYmFzZUlkVG9rZW4gPSB7XG4gICAgLy8gU2V0IGFsbCByZXF1aXJlZCBmaWVsZHMgdG8gZGVjZW50IGRlZmF1bHRzXG4gICAgaXNzOiBgaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tLyR7cHJvamVjdH1gLFxuICAgIGF1ZDogcHJvamVjdCxcbiAgICBpYXQsXG4gICAgZXhwOiBpYXQgKyAzNjAwLFxuICAgIGF1dGhfdGltZTogaWF0LFxuICAgIHN1YixcbiAgICB1c2VyX2lkOiBzdWIsXG4gICAgZmlyZWJhc2U6IHtcbiAgICAgIHNpZ25faW5fcHJvdmlkZXI6ICdjdXN0b20nLFxuICAgICAgaWRlbnRpdGllczoge31cbiAgICB9LFxuXG4gICAgLy8gT3ZlcnJpZGUgd2l0aCB1c2VyIG9wdGlvbnNcbiAgICAuLi50b2tlblxuICB9O1xuXG4gIC8vIFVuc2VjdXJlZCBKV1RzIHVzZSB0aGUgZW1wdHkgc3RyaW5nIGFzIGEgc2lnbmF0dXJlLlxuICBjb25zdCBzaWduYXR1cmUgPSAnJztcbiAgcmV0dXJuIFtcbiAgICBiYXNlNjR1cmxFbmNvZGVXaXRob3V0UGFkZGluZyhKU09OLnN0cmluZ2lmeShoZWFkZXIpKSxcbiAgICBiYXNlNjR1cmxFbmNvZGVXaXRob3V0UGFkZGluZyhKU09OLnN0cmluZ2lmeShwYXlsb2FkKSksXG4gICAgc2lnbmF0dXJlXG4gIF0uam9pbignLicpO1xufVxuXG5pbnRlcmZhY2UgRW11bGF0b3JTdGF0dXNNYXAge1xuICBbbmFtZTogc3RyaW5nXTogYm9vbGVhbjtcbn1cbmNvbnN0IGVtdWxhdG9yU3RhdHVzOiBFbXVsYXRvclN0YXR1c01hcCA9IHt9O1xuXG5pbnRlcmZhY2UgRW11bGF0b3JTdW1tYXJ5IHtcbiAgcHJvZDogc3RyaW5nW107XG4gIGVtdWxhdG9yOiBzdHJpbmdbXTtcbn1cblxuLy8gQ2hlY2tzIHdoZXRoZXIgYW55IHByb2R1Y3RzIGFyZSBydW5uaW5nIG9uIGFuIGVtdWxhdG9yXG5mdW5jdGlvbiBnZXRFbXVsYXRvclN1bW1hcnkoKTogRW11bGF0b3JTdW1tYXJ5IHtcbiAgY29uc3Qgc3VtbWFyeTogRW11bGF0b3JTdW1tYXJ5ID0ge1xuICAgIHByb2Q6IFtdLFxuICAgIGVtdWxhdG9yOiBbXVxuICB9O1xuICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhlbXVsYXRvclN0YXR1cykpIHtcbiAgICBpZiAoZW11bGF0b3JTdGF0dXNba2V5XSkge1xuICAgICAgc3VtbWFyeS5lbXVsYXRvci5wdXNoKGtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN1bW1hcnkucHJvZC5wdXNoKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzdW1tYXJ5O1xufVxuXG5mdW5jdGlvbiBnZXRPckNyZWF0ZUVsKGlkOiBzdHJpbmcpOiB7IGNyZWF0ZWQ6IGJvb2xlYW47IGVsZW1lbnQ6IEhUTUxFbGVtZW50IH0ge1xuICBsZXQgcGFyZW50RGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpO1xuICBsZXQgY3JlYXRlZCA9IGZhbHNlO1xuICBpZiAoIXBhcmVudERpdikge1xuICAgIHBhcmVudERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHBhcmVudERpdi5zZXRBdHRyaWJ1dGUoJ2lkJywgaWQpO1xuICAgIGNyZWF0ZWQgPSB0cnVlO1xuICB9XG4gIHJldHVybiB7IGNyZWF0ZWQsIGVsZW1lbnQ6IHBhcmVudERpdiB9O1xufVxuXG5sZXQgcHJldmlvdXNseURpc21pc3NlZCA9IGZhbHNlO1xuLyoqXG4gKiBVcGRhdGVzIEVtdWxhdG9yIEJhbm5lci4gUHJpbWFyaWx5IHVzZWQgZm9yIEZpcmViYXNlIFN0dWRpb1xuICogQHBhcmFtIG5hbWVcbiAqIEBwYXJhbSBpc1J1bm5pbmdFbXVsYXRvclxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlRW11bGF0b3JCYW5uZXIoXG4gIG5hbWU6IHN0cmluZyxcbiAgaXNSdW5uaW5nRW11bGF0b3I6IGJvb2xlYW5cbik6IHZvaWQge1xuICBpZiAoXG4gICAgdHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICB0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgIWlzQ2xvdWRXb3Jrc3RhdGlvbih3aW5kb3cubG9jYXRpb24uaG9zdCkgfHxcbiAgICBlbXVsYXRvclN0YXR1c1tuYW1lXSA9PT0gaXNSdW5uaW5nRW11bGF0b3IgfHxcbiAgICBlbXVsYXRvclN0YXR1c1tuYW1lXSB8fCAvLyBJZiBhbHJlYWR5IHNldCB0byB1c2UgZW11bGF0b3IsIGNhbid0IGdvIGJhY2sgdG8gcHJvZC5cbiAgICBwcmV2aW91c2x5RGlzbWlzc2VkXG4gICkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGVtdWxhdG9yU3RhdHVzW25hbWVdID0gaXNSdW5uaW5nRW11bGF0b3I7XG5cbiAgZnVuY3Rpb24gcHJlZml4ZWRJZChpZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYF9fZmlyZWJhc2VfX2Jhbm5lcl9fJHtpZH1gO1xuICB9XG4gIGNvbnN0IGJhbm5lcklkID0gJ19fZmlyZWJhc2VfX2Jhbm5lcic7XG4gIGNvbnN0IHN1bW1hcnkgPSBnZXRFbXVsYXRvclN1bW1hcnkoKTtcbiAgY29uc3Qgc2hvd0Vycm9yID0gc3VtbWFyeS5wcm9kLmxlbmd0aCA+IDA7XG5cbiAgZnVuY3Rpb24gdGVhckRvd24oKTogdm9pZCB7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGJhbm5lcklkKTtcbiAgICBpZiAoZWxlbWVudCkge1xuICAgICAgZWxlbWVudC5yZW1vdmUoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzZXR1cEJhbm5lclN0eWxlcyhiYW5uZXJFbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICBiYW5uZXJFbC5zdHlsZS5kaXNwbGF5ID0gJ2ZsZXgnO1xuICAgIGJhbm5lckVsLnN0eWxlLmJhY2tncm91bmQgPSAnIzdmYWFmMCc7XG4gICAgYmFubmVyRWwuc3R5bGUucG9zaXRpb24gPSAnZml4ZWQnO1xuICAgIGJhbm5lckVsLnN0eWxlLmJvdHRvbSA9ICc1cHgnO1xuICAgIGJhbm5lckVsLnN0eWxlLmxlZnQgPSAnNXB4JztcbiAgICBiYW5uZXJFbC5zdHlsZS5wYWRkaW5nID0gJy41ZW0nO1xuICAgIGJhbm5lckVsLnN0eWxlLmJvcmRlclJhZGl1cyA9ICc1cHgnO1xuICAgIGJhbm5lckVsLnN0eWxlLmFsaWduSXRlbXMgPSAnY2VudGVyJztcbiAgfVxuXG4gIGZ1bmN0aW9uIHNldHVwSWNvblN0eWxlcyhwcmVwZW5kSWNvbjogU1ZHRWxlbWVudCwgaWNvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBwcmVwZW5kSWNvbi5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzI0Jyk7XG4gICAgcHJlcGVuZEljb24uc2V0QXR0cmlidXRlKCdpZCcsIGljb25JZCk7XG4gICAgcHJlcGVuZEljb24uc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMjQnKTtcbiAgICBwcmVwZW5kSWNvbi5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDI0IDI0Jyk7XG4gICAgcHJlcGVuZEljb24uc2V0QXR0cmlidXRlKCdmaWxsJywgJ25vbmUnKTtcbiAgICBwcmVwZW5kSWNvbi5zdHlsZS5tYXJnaW5MZWZ0ID0gJy02cHgnO1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0dXBDbG9zZUJ0bigpOiBIVE1MU3BhbkVsZW1lbnQge1xuICAgIGNvbnN0IGNsb3NlQnRuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgIGNsb3NlQnRuLnN0eWxlLmN1cnNvciA9ICdwb2ludGVyJztcbiAgICBjbG9zZUJ0bi5zdHlsZS5tYXJnaW5MZWZ0ID0gJzE2cHgnO1xuICAgIGNsb3NlQnRuLnN0eWxlLmZvbnRTaXplID0gJzI0cHgnO1xuICAgIGNsb3NlQnRuLmlubmVySFRNTCA9ICcgJnRpbWVzOyc7XG4gICAgY2xvc2VCdG4ub25jbGljayA9ICgpID0+IHtcbiAgICAgIHByZXZpb3VzbHlEaXNtaXNzZWQgPSB0cnVlO1xuICAgICAgdGVhckRvd24oKTtcbiAgICB9O1xuICAgIHJldHVybiBjbG9zZUJ0bjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNldHVwTGlua1N0eWxlcyhcbiAgICBsZWFybk1vcmVMaW5rOiBIVE1MQW5jaG9yRWxlbWVudCxcbiAgICBsZWFybk1vcmVJZDogc3RyaW5nXG4gICk6IHZvaWQge1xuICAgIGxlYXJuTW9yZUxpbmsuc2V0QXR0cmlidXRlKCdpZCcsIGxlYXJuTW9yZUlkKTtcbiAgICBsZWFybk1vcmVMaW5rLmlubmVyVGV4dCA9ICdMZWFybiBtb3JlJztcbiAgICBsZWFybk1vcmVMaW5rLmhyZWYgPVxuICAgICAgJ2h0dHBzOi8vZmlyZWJhc2UuZ29vZ2xlLmNvbS9kb2NzL3N0dWRpby9wcmV2aWV3LWFwcHMjcHJldmlldy1iYWNrZW5kJztcbiAgICBsZWFybk1vcmVMaW5rLnNldEF0dHJpYnV0ZSgndGFyZ2V0JywgJ19fYmxhbmsnKTtcbiAgICBsZWFybk1vcmVMaW5rLnN0eWxlLnBhZGRpbmdMZWZ0ID0gJzVweCc7XG4gICAgbGVhcm5Nb3JlTGluay5zdHlsZS50ZXh0RGVjb3JhdGlvbiA9ICd1bmRlcmxpbmUnO1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0dXBEb20oKTogdm9pZCB7XG4gICAgY29uc3QgYmFubmVyID0gZ2V0T3JDcmVhdGVFbChiYW5uZXJJZCk7XG4gICAgY29uc3QgZmlyZWJhc2VUZXh0SWQgPSBwcmVmaXhlZElkKCd0ZXh0Jyk7XG4gICAgY29uc3QgZmlyZWJhc2VUZXh0OiBIVE1MU3BhbkVsZW1lbnQgPVxuICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZmlyZWJhc2VUZXh0SWQpIHx8IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICBjb25zdCBsZWFybk1vcmVJZCA9IHByZWZpeGVkSWQoJ2xlYXJubW9yZScpO1xuICAgIGNvbnN0IGxlYXJuTW9yZUxpbms6IEhUTUxBbmNob3JFbGVtZW50ID1cbiAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChsZWFybk1vcmVJZCkgYXMgSFRNTEFuY2hvckVsZW1lbnQpIHx8XG4gICAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgY29uc3QgcHJlcGVuZEljb25JZCA9IHByZWZpeGVkSWQoJ3ByZXByZW5kSWNvbicpO1xuICAgIGNvbnN0IHByZXBlbmRJY29uOiBTVkdFbGVtZW50ID1cbiAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcbiAgICAgICAgcHJlcGVuZEljb25JZFxuICAgICAgKSBhcyBIVE1MT3JTVkdFbGVtZW50IGFzIFNWR0VsZW1lbnQpIHx8XG4gICAgICBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJywgJ3N2ZycpO1xuICAgIGlmIChiYW5uZXIuY3JlYXRlZCkge1xuICAgICAgLy8gdXBkYXRlIHN0eWxlc1xuICAgICAgY29uc3QgYmFubmVyRWwgPSBiYW5uZXIuZWxlbWVudDtcbiAgICAgIHNldHVwQmFubmVyU3R5bGVzKGJhbm5lckVsKTtcbiAgICAgIHNldHVwTGlua1N0eWxlcyhsZWFybk1vcmVMaW5rLCBsZWFybk1vcmVJZCk7XG4gICAgICBjb25zdCBjbG9zZUJ0biA9IHNldHVwQ2xvc2VCdG4oKTtcbiAgICAgIHNldHVwSWNvblN0eWxlcyhwcmVwZW5kSWNvbiwgcHJlcGVuZEljb25JZCk7XG4gICAgICBiYW5uZXJFbC5hcHBlbmQocHJlcGVuZEljb24sIGZpcmViYXNlVGV4dCwgbGVhcm5Nb3JlTGluaywgY2xvc2VCdG4pO1xuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChiYW5uZXJFbCk7XG4gICAgfVxuXG4gICAgaWYgKHNob3dFcnJvcikge1xuICAgICAgZmlyZWJhc2VUZXh0LmlubmVyVGV4dCA9IGBQcmV2aWV3IGJhY2tlbmQgZGlzY29ubmVjdGVkLmA7XG4gICAgICBwcmVwZW5kSWNvbi5pbm5lckhUTUwgPSBgPGcgY2xpcC1wYXRoPVwidXJsKCNjbGlwMF82MDEzXzMzODU4KVwiPlxuPHBhdGggZD1cIk00LjggMTcuNkwxMiA1LjZMMTkuMiAxNy42SDQuOFpNNi45MTY2NyAxNi40SDE3LjA4MzNMMTIgNy45MzMzM0w2LjkxNjY3IDE2LjRaTTEyIDE1LjZDMTIuMTY2NyAxNS42IDEyLjMwNTYgMTUuNTQ0NCAxMi40MTY3IDE1LjQzMzNDMTIuNTM4OSAxNS4zMTExIDEyLjYgMTUuMTY2NyAxMi42IDE1QzEyLjYgMTQuODMzMyAxMi41Mzg5IDE0LjY5NDQgMTIuNDE2NyAxNC41ODMzQzEyLjMwNTYgMTQuNDYxMSAxMi4xNjY3IDE0LjQgMTIgMTQuNEMxMS44MzMzIDE0LjQgMTEuNjg4OSAxNC40NjExIDExLjU2NjcgMTQuNTgzM0MxMS40NTU2IDE0LjY5NDQgMTEuNCAxNC44MzMzIDExLjQgMTVDMTEuNCAxNS4xNjY3IDExLjQ1NTYgMTUuMzExMSAxMS41NjY3IDE1LjQzMzNDMTEuNjg4OSAxNS41NDQ0IDExLjgzMzMgMTUuNiAxMiAxNS42Wk0xMS40IDEzLjZIMTIuNlYxMC40SDExLjRWMTMuNlpcIiBmaWxsPVwiIzIxMjEyMVwiLz5cbjwvZz5cbjxkZWZzPlxuPGNsaXBQYXRoIGlkPVwiY2xpcDBfNjAxM18zMzg1OFwiPlxuPHJlY3Qgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgZmlsbD1cIndoaXRlXCIvPlxuPC9jbGlwUGF0aD5cbjwvZGVmcz5gO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcmVwZW5kSWNvbi5pbm5lckhUTUwgPSBgPGcgY2xpcC1wYXRoPVwidXJsKCNjbGlwMF82MDgzXzM0ODA0KVwiPlxuPHBhdGggZD1cIk0xMS40IDE1LjJIMTIuNlYxMS4ySDExLjRWMTUuMlpNMTIgMTBDMTIuMTY2NyAxMCAxMi4zMDU2IDkuOTQ0NDQgMTIuNDE2NyA5LjgzMzMzQzEyLjUzODkgOS43MTExMSAxMi42IDkuNTY2NjcgMTIuNiA5LjRDMTIuNiA5LjIzMzMzIDEyLjUzODkgOS4wOTQ0NCAxMi40MTY3IDguOTgzMzNDMTIuMzA1NiA4Ljg2MTExIDEyLjE2NjcgOC44IDEyIDguOEMxMS44MzMzIDguOCAxMS42ODg5IDguODYxMTEgMTEuNTY2NyA4Ljk4MzMzQzExLjQ1NTYgOS4wOTQ0NCAxMS40IDkuMjMzMzMgMTEuNCA5LjRDMTEuNCA5LjU2NjY3IDExLjQ1NTYgOS43MTExMSAxMS41NjY3IDkuODMzMzNDMTEuNjg4OSA5Ljk0NDQ0IDExLjgzMzMgMTAgMTIgMTBaTTEyIDE4LjRDMTEuMTIyMiAxOC40IDEwLjI5NDQgMTguMjMzMyA5LjUxNjY3IDE3LjlDOC43Mzg4OSAxNy41NjY3IDguMDU1NTYgMTcuMTExMSA3LjQ2NjY3IDE2LjUzMzNDNi44ODg4OSAxNS45NDQ0IDYuNDMzMzMgMTUuMjYxMSA2LjEgMTQuNDgzM0M1Ljc2NjY3IDEzLjcwNTYgNS42IDEyLjg3NzggNS42IDEyQzUuNiAxMS4xMTExIDUuNzY2NjcgMTAuMjgzMyA2LjEgOS41MTY2N0M2LjQzMzMzIDguNzM4ODkgNi44ODg4OSA4LjA2MTExIDcuNDY2NjcgNy40ODMzM0M4LjA1NTU2IDYuODk0NDQgOC43Mzg4OSA2LjQzMzMzIDkuNTE2NjcgNi4xQzEwLjI5NDQgNS43NjY2NyAxMS4xMjIyIDUuNiAxMiA1LjZDMTIuODg4OSA1LjYgMTMuNzE2NyA1Ljc2NjY3IDE0LjQ4MzMgNi4xQzE1LjI2MTEgNi40MzMzMyAxNS45Mzg5IDYuODk0NDQgMTYuNTE2NyA3LjQ4MzMzQzE3LjEwNTYgOC4wNjExMSAxNy41NjY3IDguNzM4ODkgMTcuOSA5LjUxNjY3QzE4LjIzMzMgMTAuMjgzMyAxOC40IDExLjExMTEgMTguNCAxMkMxOC40IDEyLjg3NzggMTguMjMzMyAxMy43MDU2IDE3LjkgMTQuNDgzM0MxNy41NjY3IDE1LjI2MTEgMTcuMTA1NiAxNS45NDQ0IDE2LjUxNjcgMTYuNTMzM0MxNS45Mzg5IDE3LjExMTEgMTUuMjYxMSAxNy41NjY3IDE0LjQ4MzMgMTcuOUMxMy43MTY3IDE4LjIzMzMgMTIuODg4OSAxOC40IDEyIDE4LjRaTTEyIDE3LjJDMTMuNDQ0NCAxNy4yIDE0LjY3MjIgMTYuNjk0NCAxNS42ODMzIDE1LjY4MzNDMTYuNjk0NCAxNC42NzIyIDE3LjIgMTMuNDQ0NCAxNy4yIDEyQzE3LjIgMTAuNTU1NiAxNi42OTQ0IDkuMzI3NzggMTUuNjgzMyA4LjMxNjY3QzE0LjY3MjIgNy4zMDU1NSAxMy40NDQ0IDYuOCAxMiA2LjhDMTAuNTU1NiA2LjggOS4zMjc3OCA3LjMwNTU1IDguMzE2NjcgOC4zMTY2N0M3LjMwNTU2IDkuMzI3NzggNi44IDEwLjU1NTYgNi44IDEyQzYuOCAxMy40NDQ0IDcuMzA1NTYgMTQuNjcyMiA4LjMxNjY3IDE1LjY4MzNDOS4zMjc3OCAxNi42OTQ0IDEwLjU1NTYgMTcuMiAxMiAxNy4yWlwiIGZpbGw9XCIjMjEyMTIxXCIvPlxuPC9nPlxuPGRlZnM+XG48Y2xpcFBhdGggaWQ9XCJjbGlwMF82MDgzXzM0ODA0XCI+XG48cmVjdCB3aWR0aD1cIjI0XCIgaGVpZ2h0PVwiMjRcIiBmaWxsPVwid2hpdGVcIi8+XG48L2NsaXBQYXRoPlxuPC9kZWZzPmA7XG4gICAgICBmaXJlYmFzZVRleHQuaW5uZXJUZXh0ID0gJ1ByZXZpZXcgYmFja2VuZCBydW5uaW5nIGluIHRoaXMgd29ya3NwYWNlLic7XG4gICAgfVxuICAgIGZpcmViYXNlVGV4dC5zZXRBdHRyaWJ1dGUoJ2lkJywgZmlyZWJhc2VUZXh0SWQpO1xuICB9XG4gIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycpIHtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIHNldHVwRG9tKTtcbiAgfSBlbHNlIHtcbiAgICBzZXR1cERvbSgpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQ09OU1RBTlRTIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0RGVmYXVsdHMgfSBmcm9tICcuL2RlZmF1bHRzJztcblxuLyoqXG4gKiBUeXBlIHBsYWNlaG9sZGVyIGZvciBgV29ya2VyR2xvYmFsU2NvcGVgIGZyb20gYHdlYndvcmtlcmBcbiAqL1xuZGVjbGFyZSBjbGFzcyBXb3JrZXJHbG9iYWxTY29wZSB7fVxuXG4vKipcbiAqIFJldHVybnMgbmF2aWdhdG9yLnVzZXJBZ2VudCBzdHJpbmcgb3IgJycgaWYgaXQncyBub3QgZGVmaW5lZC5cbiAqIEByZXR1cm4gdXNlciBhZ2VudCBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFVBKCk6IHN0cmluZyB7XG4gIGlmIChcbiAgICB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIHR5cGVvZiBuYXZpZ2F0b3JbJ3VzZXJBZ2VudCddID09PSAnc3RyaW5nJ1xuICApIHtcbiAgICByZXR1cm4gbmF2aWdhdG9yWyd1c2VyQWdlbnQnXTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbn1cblxuLyoqXG4gKiBEZXRlY3QgQ29yZG92YSAvIFBob25lR2FwIC8gSW9uaWMgZnJhbWV3b3JrcyBvbiBhIG1vYmlsZSBkZXZpY2UuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGRvZXMgbm90IHJlbHkgb24gY2hlY2tpbmcgYGZpbGU6Ly9gIFVSTHMgKGFzIHRoaXMgZmFpbHMgUGhvbmVHYXBcbiAqIGluIHRoZSBSaXBwbGUgZW11bGF0b3IpIG5vciBDb3Jkb3ZhIGBvbkRldmljZVJlYWR5YCwgd2hpY2ggd291bGQgbm9ybWFsbHlcbiAqIHdhaXQgZm9yIGEgY2FsbGJhY2suXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vYmlsZUNvcmRvdmEoKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAvLyBAdHMtaWdub3JlIFNldHRpbmcgdXAgYW4gYnJvYWRseSBhcHBsaWNhYmxlIGluZGV4IHNpZ25hdHVyZSBmb3IgV2luZG93XG4gICAgLy8ganVzdCB0byBkZWFsIHdpdGggdGhpcyBjYXNlIHdvdWxkIHByb2JhYmx5IGJlIGEgYmFkIGlkZWEuXG4gICAgISEod2luZG93Wydjb3Jkb3ZhJ10gfHwgd2luZG93WydwaG9uZWdhcCddIHx8IHdpbmRvd1snUGhvbmVHYXAnXSkgJiZcbiAgICAvaW9zfGlwaG9uZXxpcG9kfGlwYWR8YW5kcm9pZHxibGFja2JlcnJ5fGllbW9iaWxlL2kudGVzdChnZXRVQSgpKVxuICApO1xufVxuXG4vKipcbiAqIERldGVjdCBOb2RlLmpzLlxuICpcbiAqIEByZXR1cm4gdHJ1ZSBpZiBOb2RlLmpzIGVudmlyb25tZW50IGlzIGRldGVjdGVkIG9yIHNwZWNpZmllZC5cbiAqL1xuLy8gTm9kZSBkZXRlY3Rpb24gbG9naWMgZnJvbTogaHR0cHM6Ly9naXRodWIuY29tL2lsaWFrYW4vZGV0ZWN0LW5vZGUvXG5leHBvcnQgZnVuY3Rpb24gaXNOb2RlKCk6IGJvb2xlYW4ge1xuICBjb25zdCBmb3JjZUVudmlyb25tZW50ID0gZ2V0RGVmYXVsdHMoKT8uZm9yY2VFbnZpcm9ubWVudDtcbiAgaWYgKGZvcmNlRW52aXJvbm1lbnQgPT09ICdub2RlJykge1xuICAgIHJldHVybiB0cnVlO1xuICB9IGVsc2UgaWYgKGZvcmNlRW52aXJvbm1lbnQgPT09ICdicm93c2VyJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIChcbiAgICAgIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChnbG9iYWwucHJvY2VzcykgPT09ICdbb2JqZWN0IHByb2Nlc3NdJ1xuICAgICk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBEZXRlY3QgQnJvd3NlciBFbnZpcm9ubWVudC5cbiAqIE5vdGU6IFRoaXMgd2lsbCByZXR1cm4gdHJ1ZSBmb3IgY2VydGFpbiB0ZXN0IGZyYW1ld29ya3MgdGhhdCBhcmUgaW5jb21wbGV0ZWx5XG4gKiBtaW1pY2tpbmcgYSBicm93c2VyLCBhbmQgc2hvdWxkIG5vdCBsZWFkIHRvIGFzc3VtaW5nIGFsbCBicm93c2VyIEFQSXMgYXJlXG4gKiBhdmFpbGFibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Jyb3dzZXIoKTogYm9vbGVhbiB7XG4gIHJldHVybiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyB8fCBpc1dlYldvcmtlcigpO1xufVxuXG4vKipcbiAqIERldGVjdCBXZWIgV29ya2VyIGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1dlYldvcmtlcigpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICB0eXBlb2YgV29ya2VyR2xvYmFsU2NvcGUgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmXG4gICAgc2VsZiBpbnN0YW5jZW9mIFdvcmtlckdsb2JhbFNjb3BlXG4gICk7XG59XG5cbi8qKlxuICogRGV0ZWN0IENsb3VkZmxhcmUgV29ya2VyIGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Nsb3VkZmxhcmVXb3JrZXIoKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICBuYXZpZ2F0b3IudXNlckFnZW50ID09PSAnQ2xvdWRmbGFyZS1Xb3JrZXJzJ1xuICApO1xufVxuXG4vKipcbiAqIERldGVjdCBicm93c2VyIGV4dGVuc2lvbnMgKENocm9tZSBhbmQgRmlyZWZveCBhdCBsZWFzdCkuXG4gKi9cbmludGVyZmFjZSBCcm93c2VyUnVudGltZSB7XG4gIGlkPzogdW5rbm93bjtcbn1cbmRlY2xhcmUgY29uc3QgY2hyb21lOiB7IHJ1bnRpbWU/OiBCcm93c2VyUnVudGltZSB9O1xuZGVjbGFyZSBjb25zdCBicm93c2VyOiB7IHJ1bnRpbWU/OiBCcm93c2VyUnVudGltZSB9O1xuZXhwb3J0IGZ1bmN0aW9uIGlzQnJvd3NlckV4dGVuc2lvbigpOiBib29sZWFuIHtcbiAgY29uc3QgcnVudGltZSA9XG4gICAgdHlwZW9mIGNocm9tZSA9PT0gJ29iamVjdCdcbiAgICAgID8gY2hyb21lLnJ1bnRpbWVcbiAgICAgIDogdHlwZW9mIGJyb3dzZXIgPT09ICdvYmplY3QnXG4gICAgICA/IGJyb3dzZXIucnVudGltZVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIHJldHVybiB0eXBlb2YgcnVudGltZSA9PT0gJ29iamVjdCcgJiYgcnVudGltZS5pZCAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIERldGVjdCBSZWFjdCBOYXRpdmUuXG4gKlxuICogQHJldHVybiB0cnVlIGlmIFJlYWN0TmF0aXZlIGVudmlyb25tZW50IGlzIGRldGVjdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZWFjdE5hdGl2ZSgpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICB0eXBlb2YgbmF2aWdhdG9yID09PSAnb2JqZWN0JyAmJiBuYXZpZ2F0b3JbJ3Byb2R1Y3QnXSA9PT0gJ1JlYWN0TmF0aXZlJ1xuICApO1xufVxuXG4vKiogRGV0ZWN0cyBFbGVjdHJvbiBhcHBzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxlY3Ryb24oKTogYm9vbGVhbiB7XG4gIHJldHVybiBnZXRVQSgpLmluZGV4T2YoJ0VsZWN0cm9uLycpID49IDA7XG59XG5cbi8qKiBEZXRlY3RzIEludGVybmV0IEV4cGxvcmVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzSUUoKTogYm9vbGVhbiB7XG4gIGNvbnN0IHVhID0gZ2V0VUEoKTtcbiAgcmV0dXJuIHVhLmluZGV4T2YoJ01TSUUgJykgPj0gMCB8fCB1YS5pbmRleE9mKCdUcmlkZW50LycpID49IDA7XG59XG5cbi8qKiBEZXRlY3RzIFVuaXZlcnNhbCBXaW5kb3dzIFBsYXRmb3JtIGFwcHMuICovXG5leHBvcnQgZnVuY3Rpb24gaXNVV1AoKTogYm9vbGVhbiB7XG4gIHJldHVybiBnZXRVQSgpLmluZGV4T2YoJ01TQXBwSG9zdC8nKSA+PSAwO1xufVxuXG4vKipcbiAqIERldGVjdCB3aGV0aGVyIHRoZSBjdXJyZW50IFNESyBidWlsZCBpcyB0aGUgTm9kZSB2ZXJzaW9uLlxuICpcbiAqIEByZXR1cm4gdHJ1ZSBpZiBpdCdzIHRoZSBOb2RlIFNESyBidWlsZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTm9kZVNkaygpOiBib29sZWFuIHtcbiAgcmV0dXJuIENPTlNUQU5UUy5OT0RFX0NMSUVOVCA9PT0gdHJ1ZSB8fCBDT05TVEFOVFMuTk9ERV9BRE1JTiA9PT0gdHJ1ZTtcbn1cblxuLyoqIFJldHVybnMgdHJ1ZSBpZiB3ZSBhcmUgcnVubmluZyBpbiBTYWZhcmkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTYWZhcmkoKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgIWlzTm9kZSgpICYmXG4gICAgISFuYXZpZ2F0b3IudXNlckFnZW50ICYmXG4gICAgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmNsdWRlcygnU2FmYXJpJykgJiZcbiAgICAhbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmNsdWRlcygnQ2hyb21lJylcbiAgKTtcbn1cblxuLyoqIFJldHVybnMgdHJ1ZSBpZiB3ZSBhcmUgcnVubmluZyBpbiBTYWZhcmkgb3IgV2ViS2l0ICovXG5leHBvcnQgZnVuY3Rpb24gaXNTYWZhcmlPcldlYmtpdCgpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICAhaXNOb2RlKCkgJiZcbiAgICAhIW5hdmlnYXRvci51c2VyQWdlbnQgJiZcbiAgICAobmF2aWdhdG9yLnVzZXJBZ2VudC5pbmNsdWRlcygnU2FmYXJpJykgfHxcbiAgICAgIG5hdmlnYXRvci51c2VyQWdlbnQuaW5jbHVkZXMoJ1dlYktpdCcpKSAmJlxuICAgICFuYXZpZ2F0b3IudXNlckFnZW50LmluY2x1ZGVzKCdDaHJvbWUnKVxuICApO1xufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIGNoZWNrcyBpZiBpbmRleGVkREIgaXMgc3VwcG9ydGVkIGJ5IGN1cnJlbnQgYnJvd3Nlci9zZXJ2aWNlIHdvcmtlciBjb250ZXh0XG4gKiBAcmV0dXJuIHRydWUgaWYgaW5kZXhlZERCIGlzIHN1cHBvcnRlZCBieSBjdXJyZW50IGJyb3dzZXIvc2VydmljZSB3b3JrZXIgY29udGV4dFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNJbmRleGVkREJBdmFpbGFibGUoKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpbmRleGVkREIgPT09ICdvYmplY3QnO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyBtZXRob2QgdmFsaWRhdGVzIGJyb3dzZXIvc3cgY29udGV4dCBmb3IgaW5kZXhlZERCIGJ5IG9wZW5pbmcgYSBkdW1teSBpbmRleGVkREIgZGF0YWJhc2UgYW5kIHJlamVjdFxuICogaWYgZXJyb3JzIG9jY3VyIGR1cmluZyB0aGUgZGF0YWJhc2Ugb3BlbiBvcGVyYXRpb24uXG4gKlxuICogQHRocm93cyBleGNlcHRpb24gaWYgY3VycmVudCBicm93c2VyL3N3IGNvbnRleHQgY2FuJ3QgcnVuIGlkYi5vcGVuIChleDogU2FmYXJpIGlmcmFtZSwgRmlyZWZveFxuICogcHJpdmF0ZSBicm93c2luZylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlSW5kZXhlZERCT3BlbmFibGUoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBwcmVFeGlzdDogYm9vbGVhbiA9IHRydWU7XG4gICAgICBjb25zdCBEQl9DSEVDS19OQU1FID1cbiAgICAgICAgJ3ZhbGlkYXRlLWJyb3dzZXItY29udGV4dC1mb3ItaW5kZXhlZGRiLWFuYWx5dGljcy1tb2R1bGUnO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IHNlbGYuaW5kZXhlZERCLm9wZW4oREJfQ0hFQ0tfTkFNRSk7XG4gICAgICByZXF1ZXN0Lm9uc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgcmVxdWVzdC5yZXN1bHQuY2xvc2UoKTtcbiAgICAgICAgLy8gZGVsZXRlIGRhdGFiYXNlIG9ubHkgd2hlbiBpdCBkb2Vzbid0IHByZS1leGlzdFxuICAgICAgICBpZiAoIXByZUV4aXN0KSB7XG4gICAgICAgICAgc2VsZi5pbmRleGVkREIuZGVsZXRlRGF0YWJhc2UoREJfQ0hFQ0tfTkFNRSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZSh0cnVlKTtcbiAgICAgIH07XG4gICAgICByZXF1ZXN0Lm9udXBncmFkZW5lZWRlZCA9ICgpID0+IHtcbiAgICAgICAgcHJlRXhpc3QgPSBmYWxzZTtcbiAgICAgIH07XG5cbiAgICAgIHJlcXVlc3Qub25lcnJvciA9ICgpID0+IHtcbiAgICAgICAgcmVqZWN0KHJlcXVlc3QuZXJyb3I/Lm1lc3NhZ2UgfHwgJycpO1xuICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqXG4gKiBUaGlzIG1ldGhvZCBjaGVja3Mgd2hldGhlciBjb29raWUgaXMgZW5hYmxlZCB3aXRoaW4gY3VycmVudCBicm93c2VyXG4gKiBAcmV0dXJuIHRydWUgaWYgY29va2llIGlzIGVuYWJsZWQgd2l0aGluIGN1cnJlbnQgYnJvd3NlclxuICovXG5leHBvcnQgZnVuY3Rpb24gYXJlQ29va2llc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJyB8fCAhbmF2aWdhdG9yLmNvb2tpZUVuYWJsZWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbi8qKlxuICogQGZpbGVvdmVydmlldyBTdGFuZGFyZGl6ZWQgRmlyZWJhc2UgRXJyb3IuXG4gKlxuICogVXNhZ2U6XG4gKlxuICogICAvLyBUeXBlU2NyaXB0IHN0cmluZyBsaXRlcmFscyBmb3IgdHlwZS1zYWZlIGNvZGVzXG4gKiAgIHR5cGUgRXJyID1cbiAqICAgICAndW5rbm93bicgfFxuICogICAgICdvYmplY3Qtbm90LWZvdW5kJ1xuICogICAgIDtcbiAqXG4gKiAgIC8vIENsb3N1cmUgZW51bSBmb3IgdHlwZS1zYWZlIGVycm9yIGNvZGVzXG4gKiAgIC8vIGF0LWVudW0ge3N0cmluZ31cbiAqICAgdmFyIEVyciA9IHtcbiAqICAgICBVTktOT1dOOiAndW5rbm93bicsXG4gKiAgICAgT0JKRUNUX05PVF9GT1VORDogJ29iamVjdC1ub3QtZm91bmQnLFxuICogICB9XG4gKlxuICogICBsZXQgZXJyb3JzOiBNYXA8RXJyLCBzdHJpbmc+ID0ge1xuICogICAgICdnZW5lcmljLWVycm9yJzogXCJVbmtub3duIGVycm9yXCIsXG4gKiAgICAgJ2ZpbGUtbm90LWZvdW5kJzogXCJDb3VsZCBub3QgZmluZCBmaWxlOiB7JGZpbGV9XCIsXG4gKiAgIH07XG4gKlxuICogICAvLyBUeXBlLXNhZmUgZnVuY3Rpb24gLSBtdXN0IHBhc3MgYSB2YWxpZCBlcnJvciBjb2RlIGFzIHBhcmFtLlxuICogICBsZXQgZXJyb3IgPSBuZXcgRXJyb3JGYWN0b3J5PEVycj4oJ3NlcnZpY2UnLCAnU2VydmljZScsIGVycm9ycyk7XG4gKlxuICogICAuLi5cbiAqICAgdGhyb3cgZXJyb3IuY3JlYXRlKEVyci5HRU5FUklDKTtcbiAqICAgLi4uXG4gKiAgIHRocm93IGVycm9yLmNyZWF0ZShFcnIuRklMRV9OT1RfRk9VTkQsIHsnZmlsZSc6IGZpbGVOYW1lfSk7XG4gKiAgIC4uLlxuICogICAvLyBTZXJ2aWNlOiBDb3VsZCBub3QgZmlsZSBmaWxlOiBmb28udHh0IChzZXJ2aWNlL2ZpbGUtbm90LWZvdW5kKS5cbiAqXG4gKiAgIGNhdGNoIChlKSB7XG4gKiAgICAgYXNzZXJ0KGUubWVzc2FnZSA9PT0gXCJDb3VsZCBub3QgZmluZCBmaWxlOiBmb28udHh0LlwiKTtcbiAqICAgICBpZiAoKGUgYXMgRmlyZWJhc2VFcnJvcik/LmNvZGUgPT09ICdzZXJ2aWNlL2ZpbGUtbm90LWZvdW5kJykge1xuICogICAgICAgY29uc29sZS5sb2coXCJDb3VsZCBub3QgcmVhZCBmaWxlOiBcIiArIGVbJ2ZpbGUnXSk7XG4gKiAgICAgfVxuICogICB9XG4gKi9cblxuZXhwb3J0IHR5cGUgRXJyb3JNYXA8RXJyb3JDb2RlIGV4dGVuZHMgc3RyaW5nPiA9IHtcbiAgcmVhZG9ubHkgW0sgaW4gRXJyb3JDb2RlXTogc3RyaW5nO1xufTtcblxuY29uc3QgRVJST1JfTkFNRSA9ICdGaXJlYmFzZUVycm9yJztcblxuZXhwb3J0IGludGVyZmFjZSBTdHJpbmdMaWtlIHtcbiAgdG9TdHJpbmcoKTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVycm9yRGF0YSB7XG4gIFtrZXk6IHN0cmluZ106IHVua25vd247XG59XG5cbi8vIEJhc2VkIG9uIGNvZGUgZnJvbTpcbi8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yI0N1c3RvbV9FcnJvcl9UeXBlc1xuZXhwb3J0IGNsYXNzIEZpcmViYXNlRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIC8qKiBUaGUgY3VzdG9tIG5hbWUgZm9yIGFsbCBGaXJlYmFzZUVycm9ycy4gKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nID0gRVJST1JfTkFNRTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICAvKiogVGhlIGVycm9yIGNvZGUgZm9yIHRoaXMgZXJyb3IuICovXG4gICAgcmVhZG9ubHkgY29kZTogc3RyaW5nLFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICAvKiogQ3VzdG9tIGRhdGEgZm9yIHRoaXMgZXJyb3IuICovXG4gICAgcHVibGljIGN1c3RvbURhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgIC8vIEZpeCBGb3IgRVM1XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL01pY3Jvc29mdC9UeXBlU2NyaXB0LXdpa2kvYmxvYi9tYXN0ZXIvQnJlYWtpbmctQ2hhbmdlcy5tZCNleHRlbmRpbmctYnVpbHQtaW5zLWxpa2UtZXJyb3ItYXJyYXktYW5kLW1hcC1tYXktbm8tbG9uZ2VyLXdvcmtcbiAgICAvLyBUT0RPKGRsYXJvY3F1ZSk6IFJlcGxhY2UgdGhpcyB3aXRoIGBuZXcudGFyZ2V0YDogaHR0cHM6Ly93d3cudHlwZXNjcmlwdGxhbmcub3JnL2RvY3MvaGFuZGJvb2svcmVsZWFzZS1ub3Rlcy90eXBlc2NyaXB0LTItMi5odG1sI3N1cHBvcnQtZm9yLW5ld3RhcmdldFxuICAgIC8vICAgICAgICAgICAgICAgICAgIHdoaWNoIHdlIGNhbiBub3cgdXNlIHNpbmNlIHdlIG5vIGxvbmdlciB0YXJnZXQgRVM1LlxuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBGaXJlYmFzZUVycm9yLnByb3RvdHlwZSk7XG5cbiAgICAvLyBNYWludGFpbnMgcHJvcGVyIHN0YWNrIHRyYWNlIGZvciB3aGVyZSBvdXIgZXJyb3Igd2FzIHRocm93bi5cbiAgICAvLyBPbmx5IGF2YWlsYWJsZSBvbiBWOC5cbiAgICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIEVycm9yRmFjdG9yeS5wcm90b3R5cGUuY3JlYXRlKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEVycm9yRmFjdG9yeTxcbiAgRXJyb3JDb2RlIGV4dGVuZHMgc3RyaW5nLFxuICBFcnJvclBhcmFtcyBleHRlbmRzIHsgcmVhZG9ubHkgW0sgaW4gRXJyb3JDb2RlXT86IEVycm9yRGF0YSB9ID0ge31cbj4ge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2U6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2VOYW1lOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBlcnJvcnM6IEVycm9yTWFwPEVycm9yQ29kZT5cbiAgKSB7fVxuXG4gIGNyZWF0ZTxLIGV4dGVuZHMgRXJyb3JDb2RlPihcbiAgICBjb2RlOiBLLFxuICAgIC4uLmRhdGE6IEsgZXh0ZW5kcyBrZXlvZiBFcnJvclBhcmFtcyA/IFtFcnJvclBhcmFtc1tLXV0gOiBbXVxuICApOiBGaXJlYmFzZUVycm9yIHtcbiAgICBjb25zdCBjdXN0b21EYXRhID0gKGRhdGFbMF0gYXMgRXJyb3JEYXRhKSB8fCB7fTtcbiAgICBjb25zdCBmdWxsQ29kZSA9IGAke3RoaXMuc2VydmljZX0vJHtjb2RlfWA7XG4gICAgY29uc3QgdGVtcGxhdGUgPSB0aGlzLmVycm9yc1tjb2RlXTtcblxuICAgIGNvbnN0IG1lc3NhZ2UgPSB0ZW1wbGF0ZSA/IHJlcGxhY2VUZW1wbGF0ZSh0ZW1wbGF0ZSwgY3VzdG9tRGF0YSkgOiAnRXJyb3InO1xuICAgIC8vIFNlcnZpY2UgTmFtZTogRXJyb3IgbWVzc2FnZSAoc2VydmljZS9jb2RlKS5cbiAgICBjb25zdCBmdWxsTWVzc2FnZSA9IGAke3RoaXMuc2VydmljZU5hbWV9OiAke21lc3NhZ2V9ICgke2Z1bGxDb2RlfSkuYDtcblxuICAgIGNvbnN0IGVycm9yID0gbmV3IEZpcmViYXNlRXJyb3IoZnVsbENvZGUsIGZ1bGxNZXNzYWdlLCBjdXN0b21EYXRhKTtcblxuICAgIHJldHVybiBlcnJvcjtcbiAgfVxufVxuXG5mdW5jdGlvbiByZXBsYWNlVGVtcGxhdGUodGVtcGxhdGU6IHN0cmluZywgZGF0YTogRXJyb3JEYXRhKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRlbXBsYXRlLnJlcGxhY2UoUEFUVEVSTiwgKF8sIGtleSkgPT4ge1xuICAgIGNvbnN0IHZhbHVlID0gZGF0YVtrZXldO1xuICAgIHJldHVybiB2YWx1ZSAhPSBudWxsID8gU3RyaW5nKHZhbHVlKSA6IGA8JHtrZXl9Pz5gO1xuICB9KTtcbn1cblxuY29uc3QgUEFUVEVSTiA9IC9cXHtcXCQoW159XSspfS9nO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogRXZhbHVhdGVzIGEgSlNPTiBzdHJpbmcgaW50byBhIGphdmFzY3JpcHQgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgQSBzdHJpbmcgY29udGFpbmluZyBKU09OLlxuICogQHJldHVybiB7Kn0gVGhlIGphdmFzY3JpcHQgb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgc3BlY2lmaWVkIEpTT04uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBqc29uRXZhbChzdHI6IHN0cmluZyk6IHVua25vd24ge1xuICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xufVxuXG4vKipcbiAqIFJldHVybnMgSlNPTiByZXByZXNlbnRpbmcgYSBqYXZhc2NyaXB0IG9iamVjdC5cbiAqIEBwYXJhbSB7Kn0gZGF0YSBKYXZhU2NyaXB0IG9iamVjdCB0byBiZSBzdHJpbmdpZmllZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIEpTT04gY29udGVudHMgb2YgdGhlIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0cmluZ2lmeShkYXRhOiB1bmtub3duKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGRhdGEpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGJhc2U2NERlY29kZSB9IGZyb20gJy4vY3J5cHQnO1xuaW1wb3J0IHsganNvbkV2YWwgfSBmcm9tICcuL2pzb24nO1xuXG5pbnRlcmZhY2UgQ2xhaW1zIHtcbiAgW2tleTogc3RyaW5nXToge307XG59XG5cbmludGVyZmFjZSBEZWNvZGVkVG9rZW4ge1xuICBoZWFkZXI6IG9iamVjdDtcbiAgY2xhaW1zOiBDbGFpbXM7XG4gIGRhdGE6IG9iamVjdDtcbiAgc2lnbmF0dXJlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVjb2RlcyBhIEZpcmViYXNlIGF1dGguIHRva2VuIGludG8gY29uc3RpdHVlbnQgcGFydHMuXG4gKlxuICogTm90ZXM6XG4gKiAtIE1heSByZXR1cm4gd2l0aCBpbnZhbGlkIC8gaW5jb21wbGV0ZSBjbGFpbXMgaWYgdGhlcmUncyBubyBuYXRpdmUgYmFzZTY0IGRlY29kaW5nIHN1cHBvcnQuXG4gKiAtIERvZXNuJ3QgY2hlY2sgaWYgdGhlIHRva2VuIGlzIGFjdHVhbGx5IHZhbGlkLlxuICovXG5leHBvcnQgY29uc3QgZGVjb2RlID0gZnVuY3Rpb24gKHRva2VuOiBzdHJpbmcpOiBEZWNvZGVkVG9rZW4ge1xuICBsZXQgaGVhZGVyID0ge30sXG4gICAgY2xhaW1zOiBDbGFpbXMgPSB7fSxcbiAgICBkYXRhID0ge30sXG4gICAgc2lnbmF0dXJlID0gJyc7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwYXJ0cyA9IHRva2VuLnNwbGl0KCcuJyk7XG4gICAgaGVhZGVyID0ganNvbkV2YWwoYmFzZTY0RGVjb2RlKHBhcnRzWzBdKSB8fCAnJykgYXMgb2JqZWN0O1xuICAgIGNsYWltcyA9IGpzb25FdmFsKGJhc2U2NERlY29kZShwYXJ0c1sxXSkgfHwgJycpIGFzIENsYWltcztcbiAgICBzaWduYXR1cmUgPSBwYXJ0c1syXTtcbiAgICBkYXRhID0gY2xhaW1zWydkJ10gfHwge307XG4gICAgZGVsZXRlIGNsYWltc1snZCddO1xuICB9IGNhdGNoIChlKSB7fVxuXG4gIHJldHVybiB7XG4gICAgaGVhZGVyLFxuICAgIGNsYWltcyxcbiAgICBkYXRhLFxuICAgIHNpZ25hdHVyZVxuICB9O1xufTtcblxuaW50ZXJmYWNlIERlY29kZWRUb2tlbiB7XG4gIGhlYWRlcjogb2JqZWN0O1xuICBjbGFpbXM6IENsYWltcztcbiAgZGF0YTogb2JqZWN0O1xuICBzaWduYXR1cmU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBEZWNvZGVzIGEgRmlyZWJhc2UgYXV0aC4gdG9rZW4gYW5kIGNoZWNrcyB0aGUgdmFsaWRpdHkgb2YgaXRzIHRpbWUtYmFzZWQgY2xhaW1zLiBXaWxsIHJldHVybiB0cnVlIGlmIHRoZVxuICogdG9rZW4gaXMgd2l0aGluIHRoZSB0aW1lIHdpbmRvdyBhdXRob3JpemVkIGJ5IHRoZSAnbmJmJyAobm90LWJlZm9yZSkgYW5kICdpYXQnIChpc3N1ZWQtYXQpIGNsYWltcy5cbiAqXG4gKiBOb3RlczpcbiAqIC0gTWF5IHJldHVybiBhIGZhbHNlIG5lZ2F0aXZlIGlmIHRoZXJlJ3Mgbm8gbmF0aXZlIGJhc2U2NCBkZWNvZGluZyBzdXBwb3J0LlxuICogLSBEb2Vzbid0IGNoZWNrIGlmIHRoZSB0b2tlbiBpcyBhY3R1YWxseSB2YWxpZC5cbiAqL1xuZXhwb3J0IGNvbnN0IGlzVmFsaWRUaW1lc3RhbXAgPSBmdW5jdGlvbiAodG9rZW46IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBjbGFpbXM6IENsYWltcyA9IGRlY29kZSh0b2tlbikuY2xhaW1zO1xuICBjb25zdCBub3c6IG51bWJlciA9IE1hdGguZmxvb3IobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKTtcbiAgbGV0IHZhbGlkU2luY2U6IG51bWJlciA9IDAsXG4gICAgdmFsaWRVbnRpbDogbnVtYmVyID0gMDtcblxuICBpZiAodHlwZW9mIGNsYWltcyA9PT0gJ29iamVjdCcpIHtcbiAgICBpZiAoY2xhaW1zLmhhc093blByb3BlcnR5KCduYmYnKSkge1xuICAgICAgdmFsaWRTaW5jZSA9IGNsYWltc1snbmJmJ10gYXMgbnVtYmVyO1xuICAgIH0gZWxzZSBpZiAoY2xhaW1zLmhhc093blByb3BlcnR5KCdpYXQnKSkge1xuICAgICAgdmFsaWRTaW5jZSA9IGNsYWltc1snaWF0J10gYXMgbnVtYmVyO1xuICAgIH1cblxuICAgIGlmIChjbGFpbXMuaGFzT3duUHJvcGVydHkoJ2V4cCcpKSB7XG4gICAgICB2YWxpZFVudGlsID0gY2xhaW1zWydleHAnXSBhcyBudW1iZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHRva2VuIHdpbGwgZXhwaXJlIGFmdGVyIDI0aCBieSBkZWZhdWx0XG4gICAgICB2YWxpZFVudGlsID0gdmFsaWRTaW5jZSArIDg2NDAwO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAoXG4gICAgISFub3cgJiZcbiAgICAhIXZhbGlkU2luY2UgJiZcbiAgICAhIXZhbGlkVW50aWwgJiZcbiAgICBub3cgPj0gdmFsaWRTaW5jZSAmJlxuICAgIG5vdyA8PSB2YWxpZFVudGlsXG4gICk7XG59O1xuXG4vKipcbiAqIERlY29kZXMgYSBGaXJlYmFzZSBhdXRoLiB0b2tlbiBhbmQgcmV0dXJucyBpdHMgaXNzdWVkIGF0IHRpbWUgaWYgdmFsaWQsIG51bGwgb3RoZXJ3aXNlLlxuICpcbiAqIE5vdGVzOlxuICogLSBNYXkgcmV0dXJuIG51bGwgaWYgdGhlcmUncyBubyBuYXRpdmUgYmFzZTY0IGRlY29kaW5nIHN1cHBvcnQuXG4gKiAtIERvZXNuJ3QgY2hlY2sgaWYgdGhlIHRva2VuIGlzIGFjdHVhbGx5IHZhbGlkLlxuICovXG5leHBvcnQgY29uc3QgaXNzdWVkQXRUaW1lID0gZnVuY3Rpb24gKHRva2VuOiBzdHJpbmcpOiBudW1iZXIgfCBudWxsIHtcbiAgY29uc3QgY2xhaW1zOiBDbGFpbXMgPSBkZWNvZGUodG9rZW4pLmNsYWltcztcbiAgaWYgKHR5cGVvZiBjbGFpbXMgPT09ICdvYmplY3QnICYmIGNsYWltcy5oYXNPd25Qcm9wZXJ0eSgnaWF0JykpIHtcbiAgICByZXR1cm4gY2xhaW1zWydpYXQnXSBhcyBudW1iZXI7XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59O1xuXG4vKipcbiAqIERlY29kZXMgYSBGaXJlYmFzZSBhdXRoLiB0b2tlbiBhbmQgY2hlY2tzIHRoZSB2YWxpZGl0eSBvZiBpdHMgZm9ybWF0LiBFeHBlY3RzIGEgdmFsaWQgaXNzdWVkLWF0IHRpbWUuXG4gKlxuICogTm90ZXM6XG4gKiAtIE1heSByZXR1cm4gYSBmYWxzZSBuZWdhdGl2ZSBpZiB0aGVyZSdzIG5vIG5hdGl2ZSBiYXNlNjQgZGVjb2Rpbmcgc3VwcG9ydC5cbiAqIC0gRG9lc24ndCBjaGVjayBpZiB0aGUgdG9rZW4gaXMgYWN0dWFsbHkgdmFsaWQuXG4gKi9cbmV4cG9ydCBjb25zdCBpc1ZhbGlkRm9ybWF0ID0gZnVuY3Rpb24gKHRva2VuOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgZGVjb2RlZCA9IGRlY29kZSh0b2tlbiksXG4gICAgY2xhaW1zID0gZGVjb2RlZC5jbGFpbXM7XG5cbiAgcmV0dXJuICEhY2xhaW1zICYmIHR5cGVvZiBjbGFpbXMgPT09ICdvYmplY3QnICYmIGNsYWltcy5oYXNPd25Qcm9wZXJ0eSgnaWF0Jyk7XG59O1xuXG4vKipcbiAqIEF0dGVtcHRzIHRvIHBlZXIgaW50byBhbiBhdXRoIHRva2VuIGFuZCBkZXRlcm1pbmUgaWYgaXQncyBhbiBhZG1pbiBhdXRoIHRva2VuIGJ5IGxvb2tpbmcgYXQgdGhlIGNsYWltcyBwb3J0aW9uLlxuICpcbiAqIE5vdGVzOlxuICogLSBNYXkgcmV0dXJuIGEgZmFsc2UgbmVnYXRpdmUgaWYgdGhlcmUncyBubyBuYXRpdmUgYmFzZTY0IGRlY29kaW5nIHN1cHBvcnQuXG4gKiAtIERvZXNuJ3QgY2hlY2sgaWYgdGhlIHRva2VuIGlzIGFjdHVhbGx5IHZhbGlkLlxuICovXG5leHBvcnQgY29uc3QgaXNBZG1pbiA9IGZ1bmN0aW9uICh0b2tlbjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNsYWltczogQ2xhaW1zID0gZGVjb2RlKHRva2VuKS5jbGFpbXM7XG4gIHJldHVybiB0eXBlb2YgY2xhaW1zID09PSAnb2JqZWN0JyAmJiBjbGFpbXNbJ2FkbWluJ10gPT09IHRydWU7XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluczxUIGV4dGVuZHMgb2JqZWN0PihvYmo6IFQsIGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZUdldDxUIGV4dGVuZHMgb2JqZWN0LCBLIGV4dGVuZHMga2V5b2YgVD4oXG4gIG9iajogVCxcbiAga2V5OiBLXG4pOiBUW0tdIHwgdW5kZWZpbmVkIHtcbiAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkpIHtcbiAgICByZXR1cm4gb2JqW2tleV07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eShvYmo6IG9iamVjdCk6IG9iaiBpcyB7fSB7XG4gIGZvciAoY29uc3Qga2V5IGluIG9iaikge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFwPEsgZXh0ZW5kcyBzdHJpbmcsIFYsIFU+KFxuICBvYmo6IHsgW2tleSBpbiBLXTogViB9LFxuICBmbjogKHZhbHVlOiBWLCBrZXk6IEssIG9iajogeyBba2V5IGluIEtdOiBWIH0pID0+IFUsXG4gIGNvbnRleHRPYmo/OiB1bmtub3duXG4pOiB7IFtrZXkgaW4gS106IFUgfSB7XG4gIGNvbnN0IHJlczogUGFydGlhbDx7IFtrZXkgaW4gS106IFUgfT4gPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkpIHtcbiAgICAgIHJlc1trZXldID0gZm4uY2FsbChjb250ZXh0T2JqLCBvYmpba2V5XSwga2V5LCBvYmopO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzIGFzIHsgW2tleSBpbiBLXTogVSB9O1xufVxuXG4vKipcbiAqIERlZXAgZXF1YWwgdHdvIG9iamVjdHMuIFN1cHBvcnQgQXJyYXlzIGFuZCBPYmplY3RzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcEVxdWFsKGE6IG9iamVjdCwgYjogb2JqZWN0KTogYm9vbGVhbiB7XG4gIGlmIChhID09PSBiKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBhS2V5cyA9IE9iamVjdC5rZXlzKGEpO1xuICBjb25zdCBiS2V5cyA9IE9iamVjdC5rZXlzKGIpO1xuICBmb3IgKGNvbnN0IGsgb2YgYUtleXMpIHtcbiAgICBpZiAoIWJLZXlzLmluY2x1ZGVzKGspKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgYVByb3AgPSAoYSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilba107XG4gICAgY29uc3QgYlByb3AgPSAoYiBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilba107XG4gICAgaWYgKGlzT2JqZWN0KGFQcm9wKSAmJiBpc09iamVjdChiUHJvcCkpIHtcbiAgICAgIGlmICghZGVlcEVxdWFsKGFQcm9wLCBiUHJvcCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoYVByb3AgIT09IGJQcm9wKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBrIG9mIGJLZXlzKSB7XG4gICAgaWYgKCFhS2V5cy5pbmNsdWRlcyhrKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QodGhpbmc6IHVua25vd24pOiB0aGluZyBpcyBvYmplY3Qge1xuICByZXR1cm4gdGhpbmcgIT09IG51bGwgJiYgdHlwZW9mIHRoaW5nID09PSAnb2JqZWN0Jztcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBEZWZlcnJlZCB9IGZyb20gJy4vZGVmZXJyZWQnO1xuXG4vKipcbiAqIFJlamVjdHMgaWYgdGhlIGdpdmVuIHByb21pc2UgZG9lc24ndCByZXNvbHZlIGluIHRpbWVJbk1TIG1pbGxpc2Vjb25kcy5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvbWlzZVdpdGhUaW1lb3V0PFQ+KFxuICBwcm9taXNlOiBQcm9taXNlPFQ+LFxuICB0aW1lSW5NUyA9IDIwMDBcbik6IFByb21pc2U8VD4ge1xuICBjb25zdCBkZWZlcnJlZFByb21pc2UgPSBuZXcgRGVmZXJyZWQ8VD4oKTtcbiAgc2V0VGltZW91dCgoKSA9PiBkZWZlcnJlZFByb21pc2UucmVqZWN0KCd0aW1lb3V0IScpLCB0aW1lSW5NUyk7XG4gIHByb21pc2UudGhlbihkZWZlcnJlZFByb21pc2UucmVzb2x2ZSwgZGVmZXJyZWRQcm9taXNlLnJlamVjdCk7XG4gIHJldHVybiBkZWZlcnJlZFByb21pc2UucHJvbWlzZTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIFJldHVybnMgYSBxdWVyeXN0cmluZy1mb3JtYXR0ZWQgc3RyaW5nIChlLmcuICZhcmc9dmFsJmFyZzI9dmFsMikgZnJvbSBhXG4gKiBwYXJhbXMgb2JqZWN0IChlLmcuIHthcmc6ICd2YWwnLCBhcmcyOiAndmFsMid9KVxuICogTm90ZTogWW91IG11c3QgcHJlcGVuZCBpdCB3aXRoID8gd2hlbiBhZGRpbmcgaXQgdG8gYSBVUkwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBxdWVyeXN0cmluZyhxdWVyeXN0cmluZ1BhcmFtczoge1xuICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXI7XG59KTogc3RyaW5nIHtcbiAgY29uc3QgcGFyYW1zID0gW107XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5c3RyaW5nUGFyYW1zKSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgdmFsdWUuZm9yRWFjaChhcnJheVZhbCA9PiB7XG4gICAgICAgIHBhcmFtcy5wdXNoKFxuICAgICAgICAgIGVuY29kZVVSSUNvbXBvbmVudChrZXkpICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KGFycmF5VmFsKVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcmFtcy5wdXNoKGVuY29kZVVSSUNvbXBvbmVudChrZXkpICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBwYXJhbXMubGVuZ3RoID8gJyYnICsgcGFyYW1zLmpvaW4oJyYnKSA6ICcnO1xufVxuXG4vKipcbiAqIERlY29kZXMgYSBxdWVyeXN0cmluZyAoZS5nLiA/YXJnPXZhbCZhcmcyPXZhbDIpIGludG8gYSBwYXJhbXMgb2JqZWN0XG4gKiAoZS5nLiB7YXJnOiAndmFsJywgYXJnMjogJ3ZhbDInfSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHF1ZXJ5c3RyaW5nRGVjb2RlKHF1ZXJ5c3RyaW5nOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3Qgb2JqOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIGNvbnN0IHRva2VucyA9IHF1ZXJ5c3RyaW5nLnJlcGxhY2UoL15cXD8vLCAnJykuc3BsaXQoJyYnKTtcblxuICB0b2tlbnMuZm9yRWFjaCh0b2tlbiA9PiB7XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICBjb25zdCBba2V5LCB2YWx1ZV0gPSB0b2tlbi5zcGxpdCgnPScpO1xuICAgICAgb2JqW2RlY29kZVVSSUNvbXBvbmVudChrZXkpXSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG9iajtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IHRoZSBxdWVyeSBzdHJpbmcgcGFydCBvZiBhIFVSTCwgaW5jbHVkaW5nIHRoZSBsZWFkaW5nIHF1ZXN0aW9uIG1hcmsgKGlmIHByZXNlbnQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFF1ZXJ5c3RyaW5nKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcXVlcnlTdGFydCA9IHVybC5pbmRleE9mKCc/Jyk7XG4gIGlmICghcXVlcnlTdGFydCkge1xuICAgIHJldHVybiAnJztcbiAgfVxuICBjb25zdCBmcmFnbWVudFN0YXJ0ID0gdXJsLmluZGV4T2YoJyMnLCBxdWVyeVN0YXJ0KTtcbiAgcmV0dXJuIHVybC5zdWJzdHJpbmcoXG4gICAgcXVlcnlTdGFydCxcbiAgICBmcmFnbWVudFN0YXJ0ID4gMCA/IGZyYWdtZW50U3RhcnQgOiB1bmRlZmluZWRcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgU0hBLTEgY3J5cHRvZ3JhcGhpYyBoYXNoLlxuICogVmFyaWFibGUgbmFtZXMgZm9sbG93IHRoZSBub3RhdGlvbiBpbiBGSVBTIFBVQiAxODAtMzpcbiAqIGh0dHA6Ly9jc3JjLm5pc3QuZ292L3B1YmxpY2F0aW9ucy9maXBzL2ZpcHMxODAtMy9maXBzMTgwLTNfZmluYWwucGRmLlxuICpcbiAqIFVzYWdlOlxuICogICB2YXIgc2hhMSA9IG5ldyBzaGExKCk7XG4gKiAgIHNoYTEudXBkYXRlKGJ5dGVzKTtcbiAqICAgdmFyIGhhc2ggPSBzaGExLmRpZ2VzdCgpO1xuICpcbiAqIFBlcmZvcm1hbmNlOlxuICogICBDaHJvbWUgMjM6ICAgfjQwMCBNYml0L3NcbiAqICAgRmlyZWZveCAxNjogIH4yNTAgTWJpdC9zXG4gKlxuICovXG5cbi8qKlxuICogU0hBLTEgY3J5cHRvZ3JhcGhpYyBoYXNoIGNvbnN0cnVjdG9yLlxuICpcbiAqIFRoZSBwcm9wZXJ0aWVzIGRlY2xhcmVkIGhlcmUgYXJlIGRpc2N1c3NlZCBpbiB0aGUgYWJvdmUgYWxnb3JpdGhtIGRvY3VtZW50LlxuICogQGNvbnN0cnVjdG9yXG4gKiBAZmluYWxcbiAqIEBzdHJ1Y3RcbiAqL1xuZXhwb3J0IGNsYXNzIFNoYTEge1xuICAvKipcbiAgICogSG9sZHMgdGhlIHByZXZpb3VzIHZhbHVlcyBvZiBhY2N1bXVsYXRlZCB2YXJpYWJsZXMgYS1lIGluIHRoZSBjb21wcmVzc19cbiAgICogZnVuY3Rpb24uXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGNoYWluXzogbnVtYmVyW10gPSBbXTtcblxuICAvKipcbiAgICogQSBidWZmZXIgaG9sZGluZyB0aGUgcGFydGlhbGx5IGNvbXB1dGVkIGhhc2ggcmVzdWx0LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBidWZfOiBudW1iZXJbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBBbiBhcnJheSBvZiA4MCBieXRlcywgZWFjaCBhIHBhcnQgb2YgdGhlIG1lc3NhZ2UgdG8gYmUgaGFzaGVkLiAgUmVmZXJyZWQgdG9cbiAgICogYXMgdGhlIG1lc3NhZ2Ugc2NoZWR1bGUgaW4gdGhlIGRvY3MuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIFdfOiBudW1iZXJbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBDb250YWlucyBkYXRhIG5lZWRlZCB0byBwYWQgbWVzc2FnZXMgbGVzcyB0aGFuIDY0IGJ5dGVzLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBwYWRfOiBudW1iZXJbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZSB7bnVtYmVyfVxuICAgKi9cbiAgcHJpdmF0ZSBpbmJ1Zl86IG51bWJlciA9IDA7XG5cbiAgLyoqXG4gICAqIEBwcml2YXRlIHtudW1iZXJ9XG4gICAqL1xuICBwcml2YXRlIHRvdGFsXzogbnVtYmVyID0gMDtcblxuICBibG9ja1NpemU6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmJsb2NrU2l6ZSA9IDUxMiAvIDg7XG5cbiAgICB0aGlzLnBhZF9bMF0gPSAxMjg7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCB0aGlzLmJsb2NrU2l6ZTsgKytpKSB7XG4gICAgICB0aGlzLnBhZF9baV0gPSAwO1xuICAgIH1cblxuICAgIHRoaXMucmVzZXQoKTtcbiAgfVxuXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuY2hhaW5fWzBdID0gMHg2NzQ1MjMwMTtcbiAgICB0aGlzLmNoYWluX1sxXSA9IDB4ZWZjZGFiODk7XG4gICAgdGhpcy5jaGFpbl9bMl0gPSAweDk4YmFkY2ZlO1xuICAgIHRoaXMuY2hhaW5fWzNdID0gMHgxMDMyNTQ3NjtcbiAgICB0aGlzLmNoYWluX1s0XSA9IDB4YzNkMmUxZjA7XG5cbiAgICB0aGlzLmluYnVmXyA9IDA7XG4gICAgdGhpcy50b3RhbF8gPSAwO1xuICB9XG5cbiAgLyoqXG4gICAqIEludGVybmFsIGNvbXByZXNzIGhlbHBlciBmdW5jdGlvbi5cbiAgICogQHBhcmFtIGJ1ZiBCbG9jayB0byBjb21wcmVzcy5cbiAgICogQHBhcmFtIG9mZnNldCBPZmZzZXQgb2YgdGhlIGJsb2NrIGluIHRoZSBidWZmZXIuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBjb21wcmVzc18oYnVmOiBudW1iZXJbXSB8IFVpbnQ4QXJyYXkgfCBzdHJpbmcsIG9mZnNldD86IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghb2Zmc2V0KSB7XG4gICAgICBvZmZzZXQgPSAwO1xuICAgIH1cblxuICAgIGNvbnN0IFcgPSB0aGlzLldfO1xuXG4gICAgLy8gZ2V0IDE2IGJpZyBlbmRpYW4gd29yZHNcbiAgICBpZiAodHlwZW9mIGJ1ZiA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgICAvLyBUT0RPKHVzZXIpOiBbYnVnIDgxNDAxMjJdIFJlY2VudCB2ZXJzaW9ucyBvZiBTYWZhcmkgZm9yIE1hYyBPUyBhbmQgaU9TXG4gICAgICAgIC8vIGhhdmUgYSBidWcgdGhhdCB0dXJucyB0aGUgcG9zdC1pbmNyZW1lbnQgKysgb3BlcmF0b3IgaW50byBwcmUtaW5jcmVtZW50XG4gICAgICAgIC8vIGR1cmluZyBKSVQgY29tcGlsYXRpb24uICBXZSBoYXZlIGNvZGUgdGhhdCBkZXBlbmRzIGhlYXZpbHkgb24gU0hBLTEgZm9yXG4gICAgICAgIC8vIGNvcnJlY3RuZXNzIGFuZCB3aGljaCBpcyBhZmZlY3RlZCBieSB0aGlzIGJ1Zywgc28gSSd2ZSByZW1vdmVkIGFsbCB1c2VzXG4gICAgICAgIC8vIG9mIHBvc3QtaW5jcmVtZW50ICsrIGluIHdoaWNoIHRoZSByZXN1bHQgdmFsdWUgaXMgdXNlZC4gIFdlIGNhbiByZXZlcnRcbiAgICAgICAgLy8gdGhpcyBjaGFuZ2Ugb25jZSB0aGUgU2FmYXJpIGJ1Z1xuICAgICAgICAvLyAoaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTEwOTAzNikgaGFzIGJlZW4gZml4ZWQgYW5kXG4gICAgICAgIC8vIG1vc3QgY2xpZW50cyBoYXZlIGJlZW4gdXBkYXRlZC5cbiAgICAgICAgV1tpXSA9XG4gICAgICAgICAgKGJ1Zi5jaGFyQ29kZUF0KG9mZnNldCkgPDwgMjQpIHxcbiAgICAgICAgICAoYnVmLmNoYXJDb2RlQXQob2Zmc2V0ICsgMSkgPDwgMTYpIHxcbiAgICAgICAgICAoYnVmLmNoYXJDb2RlQXQob2Zmc2V0ICsgMikgPDwgOCkgfFxuICAgICAgICAgIGJ1Zi5jaGFyQ29kZUF0KG9mZnNldCArIDMpO1xuICAgICAgICBvZmZzZXQgKz0gNDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICAgIFdbaV0gPVxuICAgICAgICAgIChidWZbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICAgICAgIChidWZbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAgICAgICAoYnVmW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAgICAgICBidWZbb2Zmc2V0ICsgM107XG4gICAgICAgIG9mZnNldCArPSA0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGV4cGFuZCB0byA4MCB3b3Jkc1xuICAgIGZvciAobGV0IGkgPSAxNjsgaSA8IDgwOyBpKyspIHtcbiAgICAgIGNvbnN0IHQgPSBXW2kgLSAzXSBeIFdbaSAtIDhdIF4gV1tpIC0gMTRdIF4gV1tpIC0gMTZdO1xuICAgICAgV1tpXSA9ICgodCA8PCAxKSB8ICh0ID4+PiAzMSkpICYgMHhmZmZmZmZmZjtcbiAgICB9XG5cbiAgICBsZXQgYSA9IHRoaXMuY2hhaW5fWzBdO1xuICAgIGxldCBiID0gdGhpcy5jaGFpbl9bMV07XG4gICAgbGV0IGMgPSB0aGlzLmNoYWluX1syXTtcbiAgICBsZXQgZCA9IHRoaXMuY2hhaW5fWzNdO1xuICAgIGxldCBlID0gdGhpcy5jaGFpbl9bNF07XG4gICAgbGV0IGYsIGs7XG5cbiAgICAvLyBUT0RPKHVzZXIpOiBUcnkgdG8gdW5yb2xsIHRoaXMgbG9vcCB0byBzcGVlZCB1cCB0aGUgY29tcHV0YXRpb24uXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA4MDsgaSsrKSB7XG4gICAgICBpZiAoaSA8IDQwKSB7XG4gICAgICAgIGlmIChpIDwgMjApIHtcbiAgICAgICAgICBmID0gZCBeIChiICYgKGMgXiBkKSk7XG4gICAgICAgICAgayA9IDB4NWE4Mjc5OTk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZiA9IGIgXiBjIF4gZDtcbiAgICAgICAgICBrID0gMHg2ZWQ5ZWJhMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGkgPCA2MCkge1xuICAgICAgICAgIGYgPSAoYiAmIGMpIHwgKGQgJiAoYiB8IGMpKTtcbiAgICAgICAgICBrID0gMHg4ZjFiYmNkYztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmID0gYiBeIGMgXiBkO1xuICAgICAgICAgIGsgPSAweGNhNjJjMWQ2O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHQgPSAoKChhIDw8IDUpIHwgKGEgPj4+IDI3KSkgKyBmICsgZSArIGsgKyBXW2ldKSAmIDB4ZmZmZmZmZmY7XG4gICAgICBlID0gZDtcbiAgICAgIGQgPSBjO1xuICAgICAgYyA9ICgoYiA8PCAzMCkgfCAoYiA+Pj4gMikpICYgMHhmZmZmZmZmZjtcbiAgICAgIGIgPSBhO1xuICAgICAgYSA9IHQ7XG4gICAgfVxuXG4gICAgdGhpcy5jaGFpbl9bMF0gPSAodGhpcy5jaGFpbl9bMF0gKyBhKSAmIDB4ZmZmZmZmZmY7XG4gICAgdGhpcy5jaGFpbl9bMV0gPSAodGhpcy5jaGFpbl9bMV0gKyBiKSAmIDB4ZmZmZmZmZmY7XG4gICAgdGhpcy5jaGFpbl9bMl0gPSAodGhpcy5jaGFpbl9bMl0gKyBjKSAmIDB4ZmZmZmZmZmY7XG4gICAgdGhpcy5jaGFpbl9bM10gPSAodGhpcy5jaGFpbl9bM10gKyBkKSAmIDB4ZmZmZmZmZmY7XG4gICAgdGhpcy5jaGFpbl9bNF0gPSAodGhpcy5jaGFpbl9bNF0gKyBlKSAmIDB4ZmZmZmZmZmY7XG4gIH1cblxuICB1cGRhdGUoYnl0ZXM/OiBudW1iZXJbXSB8IFVpbnQ4QXJyYXkgfCBzdHJpbmcsIGxlbmd0aD86IG51bWJlcik6IHZvaWQge1xuICAgIC8vIFRPRE8oam9obmxlbnopOiB0aWdodGVuIHRoZSBmdW5jdGlvbiBzaWduYXR1cmUgYW5kIHJlbW92ZSB0aGlzIGNoZWNrXG4gICAgaWYgKGJ5dGVzID09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGxlbmd0aCA9IGJ5dGVzLmxlbmd0aDtcbiAgICB9XG5cbiAgICBjb25zdCBsZW5ndGhNaW51c0Jsb2NrID0gbGVuZ3RoIC0gdGhpcy5ibG9ja1NpemU7XG4gICAgbGV0IG4gPSAwO1xuICAgIC8vIFVzaW5nIGxvY2FsIGluc3RlYWQgb2YgbWVtYmVyIHZhcmlhYmxlcyBnaXZlcyB+NSUgc3BlZWR1cCBvbiBGaXJlZm94IDE2LlxuICAgIGNvbnN0IGJ1ZiA9IHRoaXMuYnVmXztcbiAgICBsZXQgaW5idWYgPSB0aGlzLmluYnVmXztcblxuICAgIC8vIFRoZSBvdXRlciB3aGlsZSBsb29wIHNob3VsZCBleGVjdXRlIGF0IG1vc3QgdHdpY2UuXG4gICAgd2hpbGUgKG4gPCBsZW5ndGgpIHtcbiAgICAgIC8vIFdoZW4gd2UgaGF2ZSBubyBkYXRhIGluIHRoZSBibG9jayB0byB0b3AgdXAsIHdlIGNhbiBkaXJlY3RseSBwcm9jZXNzIHRoZVxuICAgICAgLy8gaW5wdXQgYnVmZmVyIChhc3N1bWluZyBpdCBjb250YWlucyBzdWZmaWNpZW50IGRhdGEpLiBUaGlzIGdpdmVzIH4yNSVcbiAgICAgIC8vIHNwZWVkdXAgb24gQ2hyb21lIDIzIGFuZCB+MTUlIHNwZWVkdXAgb24gRmlyZWZveCAxNiwgYnV0IHJlcXVpcmVzIHRoYXRcbiAgICAgIC8vIHRoZSBkYXRhIGlzIHByb3ZpZGVkIGluIGxhcmdlIGNodW5rcyAob3IgaW4gbXVsdGlwbGVzIG9mIDY0IGJ5dGVzKS5cbiAgICAgIGlmIChpbmJ1ZiA9PT0gMCkge1xuICAgICAgICB3aGlsZSAobiA8PSBsZW5ndGhNaW51c0Jsb2NrKSB7XG4gICAgICAgICAgdGhpcy5jb21wcmVzc18oYnl0ZXMsIG4pO1xuICAgICAgICAgIG4gKz0gdGhpcy5ibG9ja1NpemU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBieXRlcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgd2hpbGUgKG4gPCBsZW5ndGgpIHtcbiAgICAgICAgICBidWZbaW5idWZdID0gYnl0ZXMuY2hhckNvZGVBdChuKTtcbiAgICAgICAgICArK2luYnVmO1xuICAgICAgICAgICsrbjtcbiAgICAgICAgICBpZiAoaW5idWYgPT09IHRoaXMuYmxvY2tTaXplKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXByZXNzXyhidWYpO1xuICAgICAgICAgICAgaW5idWYgPSAwO1xuICAgICAgICAgICAgLy8gSnVtcCB0byB0aGUgb3V0ZXIgbG9vcCBzbyB3ZSB1c2UgdGhlIGZ1bGwtYmxvY2sgb3B0aW1pemF0aW9uLlxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3aGlsZSAobiA8IGxlbmd0aCkge1xuICAgICAgICAgIGJ1ZltpbmJ1Zl0gPSBieXRlc1tuXTtcbiAgICAgICAgICArK2luYnVmO1xuICAgICAgICAgICsrbjtcbiAgICAgICAgICBpZiAoaW5idWYgPT09IHRoaXMuYmxvY2tTaXplKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXByZXNzXyhidWYpO1xuICAgICAgICAgICAgaW5idWYgPSAwO1xuICAgICAgICAgICAgLy8gSnVtcCB0byB0aGUgb3V0ZXIgbG9vcCBzbyB3ZSB1c2UgdGhlIGZ1bGwtYmxvY2sgb3B0aW1pemF0aW9uLlxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5pbmJ1Zl8gPSBpbmJ1ZjtcbiAgICB0aGlzLnRvdGFsXyArPSBsZW5ndGg7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICovXG4gIGRpZ2VzdCgpOiBudW1iZXJbXSB7XG4gICAgY29uc3QgZGlnZXN0OiBudW1iZXJbXSA9IFtdO1xuICAgIGxldCB0b3RhbEJpdHMgPSB0aGlzLnRvdGFsXyAqIDg7XG5cbiAgICAvLyBBZGQgcGFkIDB4ODAgMHgwMCouXG4gICAgaWYgKHRoaXMuaW5idWZfIDwgNTYpIHtcbiAgICAgIHRoaXMudXBkYXRlKHRoaXMucGFkXywgNTYgLSB0aGlzLmluYnVmXyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudXBkYXRlKHRoaXMucGFkXywgdGhpcy5ibG9ja1NpemUgLSAodGhpcy5pbmJ1Zl8gLSA1NikpO1xuICAgIH1cblxuICAgIC8vIEFkZCAjIGJpdHMuXG4gICAgZm9yIChsZXQgaSA9IHRoaXMuYmxvY2tTaXplIC0gMTsgaSA+PSA1NjsgaS0tKSB7XG4gICAgICB0aGlzLmJ1Zl9baV0gPSB0b3RhbEJpdHMgJiAyNTU7XG4gICAgICB0b3RhbEJpdHMgLz0gMjU2OyAvLyBEb24ndCB1c2UgYml0LXNoaWZ0aW5nIGhlcmUhXG4gICAgfVxuXG4gICAgdGhpcy5jb21wcmVzc18odGhpcy5idWZfKTtcblxuICAgIGxldCBuID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDU7IGkrKykge1xuICAgICAgZm9yIChsZXQgaiA9IDI0OyBqID49IDA7IGogLT0gOCkge1xuICAgICAgICBkaWdlc3Rbbl0gPSAodGhpcy5jaGFpbl9baV0gPj4gaikgJiAyNTU7XG4gICAgICAgICsrbjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpZ2VzdDtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5leHBvcnQgdHlwZSBOZXh0Rm48VD4gPSAodmFsdWU6IFQpID0+IHZvaWQ7XG5leHBvcnQgdHlwZSBFcnJvckZuID0gKGVycm9yOiBFcnJvcikgPT4gdm9pZDtcbmV4cG9ydCB0eXBlIENvbXBsZXRlRm4gPSAoKSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9ic2VydmVyPFQ+IHtcbiAgLy8gQ2FsbGVkIG9uY2UgZm9yIGVhY2ggdmFsdWUgaW4gYSBzdHJlYW0gb2YgdmFsdWVzLlxuICBuZXh0OiBOZXh0Rm48VD47XG5cbiAgLy8gQSBzdHJlYW0gdGVybWluYXRlcyBieSBhIHNpbmdsZSBjYWxsIHRvIEVJVEhFUiBlcnJvcigpIG9yIGNvbXBsZXRlKCkuXG4gIGVycm9yOiBFcnJvckZuO1xuXG4gIC8vIE5vIGV2ZW50cyB3aWxsIGJlIHNlbnQgdG8gbmV4dCgpIG9uY2UgY29tcGxldGUoKSBpcyBjYWxsZWQuXG4gIGNvbXBsZXRlOiBDb21wbGV0ZUZuO1xufVxuXG5leHBvcnQgdHlwZSBQYXJ0aWFsT2JzZXJ2ZXI8VD4gPSBQYXJ0aWFsPE9ic2VydmVyPFQ+PjtcblxuLy8gVE9ETzogU3VwcG9ydCBhbHNvIFVuc3Vic2NyaWJlLnVuc3Vic2NyaWJlP1xuZXhwb3J0IHR5cGUgVW5zdWJzY3JpYmUgPSAoKSA9PiB2b2lkO1xuXG4vKipcbiAqIFRoZSBTdWJzY3JpYmUgaW50ZXJmYWNlIGhhcyB0d28gZm9ybXMgLSBwYXNzaW5nIHRoZSBpbmxpbmUgZnVuY3Rpb25cbiAqIGNhbGxiYWNrcywgb3IgYSBvYmplY3QgaW50ZXJmYWNlIHdpdGggY2FsbGJhY2sgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdWJzY3JpYmU8VD4ge1xuICAobmV4dD86IE5leHRGbjxUPiwgZXJyb3I/OiBFcnJvckZuLCBjb21wbGV0ZT86IENvbXBsZXRlRm4pOiBVbnN1YnNjcmliZTtcbiAgKG9ic2VydmVyOiBQYXJ0aWFsT2JzZXJ2ZXI8VD4pOiBVbnN1YnNjcmliZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPYnNlcnZhYmxlPFQ+IHtcbiAgLy8gU3Vic2NyaWJlIG1ldGhvZFxuICBzdWJzY3JpYmU6IFN1YnNjcmliZTxUPjtcbn1cblxuZXhwb3J0IHR5cGUgRXhlY3V0b3I8VD4gPSAob2JzZXJ2ZXI6IE9ic2VydmVyPFQ+KSA9PiB2b2lkO1xuXG4vKipcbiAqIEhlbHBlciB0byBtYWtlIGEgU3Vic2NyaWJlIGZ1bmN0aW9uIChqdXN0IGxpa2UgUHJvbWlzZSBoZWxwcyBtYWtlIGFcbiAqIFRoZW5hYmxlKS5cbiAqXG4gKiBAcGFyYW0gZXhlY3V0b3IgRnVuY3Rpb24gd2hpY2ggY2FuIG1ha2UgY2FsbHMgdG8gYSBzaW5nbGUgT2JzZXJ2ZXJcbiAqICAgICBhcyBhIHByb3h5LlxuICogQHBhcmFtIG9uTm9PYnNlcnZlcnMgQ2FsbGJhY2sgd2hlbiBjb3VudCBvZiBPYnNlcnZlcnMgZ29lcyB0byB6ZXJvLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3Vic2NyaWJlPFQ+KFxuICBleGVjdXRvcjogRXhlY3V0b3I8VD4sXG4gIG9uTm9PYnNlcnZlcnM/OiBFeGVjdXRvcjxUPlxuKTogU3Vic2NyaWJlPFQ+IHtcbiAgY29uc3QgcHJveHkgPSBuZXcgT2JzZXJ2ZXJQcm94eTxUPihleGVjdXRvciwgb25Ob09ic2VydmVycyk7XG4gIHJldHVybiBwcm94eS5zdWJzY3JpYmUuYmluZChwcm94eSk7XG59XG5cbi8qKlxuICogSW1wbGVtZW50IGZhbi1vdXQgZm9yIGFueSBudW1iZXIgb2YgT2JzZXJ2ZXJzIGF0dGFjaGVkIHZpYSBhIHN1YnNjcmliZVxuICogZnVuY3Rpb24uXG4gKi9cbmNsYXNzIE9ic2VydmVyUHJveHk8VD4gaW1wbGVtZW50cyBPYnNlcnZlcjxUPiB7XG4gIHByaXZhdGUgb2JzZXJ2ZXJzOiBBcnJheTxPYnNlcnZlcjxUPj4gfCB1bmRlZmluZWQgPSBbXTtcbiAgcHJpdmF0ZSB1bnN1YnNjcmliZXM6IFVuc3Vic2NyaWJlW10gPSBbXTtcbiAgcHJpdmF0ZSBvbk5vT2JzZXJ2ZXJzOiBFeGVjdXRvcjxUPiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBvYnNlcnZlckNvdW50ID0gMDtcbiAgLy8gTWljcm8tdGFzayBzY2hlZHVsaW5nIGJ5IGNhbGxpbmcgdGFzay50aGVuKCkuXG4gIHByaXZhdGUgdGFzayA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBwcml2YXRlIGZpbmFsaXplZCA9IGZhbHNlO1xuICBwcml2YXRlIGZpbmFsRXJyb3I/OiBFcnJvcjtcblxuICAvKipcbiAgICogQHBhcmFtIGV4ZWN1dG9yIEZ1bmN0aW9uIHdoaWNoIGNhbiBtYWtlIGNhbGxzIHRvIGEgc2luZ2xlIE9ic2VydmVyXG4gICAqICAgICBhcyBhIHByb3h5LlxuICAgKiBAcGFyYW0gb25Ob09ic2VydmVycyBDYWxsYmFjayB3aGVuIGNvdW50IG9mIE9ic2VydmVycyBnb2VzIHRvIHplcm8uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihleGVjdXRvcjogRXhlY3V0b3I8VD4sIG9uTm9PYnNlcnZlcnM/OiBFeGVjdXRvcjxUPikge1xuICAgIHRoaXMub25Ob09ic2VydmVycyA9IG9uTm9PYnNlcnZlcnM7XG4gICAgLy8gQ2FsbCB0aGUgZXhlY3V0b3IgYXN5bmNocm9ub3VzbHkgc28gc3Vic2NyaWJlcnMgdGhhdCBhcmUgY2FsbGVkXG4gICAgLy8gc3luY2hyb25vdXNseSBhZnRlciB0aGUgY3JlYXRpb24gb2YgdGhlIHN1YnNjcmliZSBmdW5jdGlvblxuICAgIC8vIGNhbiBzdGlsbCByZWNlaXZlIHRoZSB2ZXJ5IGZpcnN0IHZhbHVlIGdlbmVyYXRlZCBpbiB0aGUgZXhlY3V0b3IuXG4gICAgdGhpcy50YXNrXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGV4ZWN1dG9yKHRoaXMpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlID0+IHtcbiAgICAgICAgdGhpcy5lcnJvcihlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgbmV4dCh2YWx1ZTogVCk6IHZvaWQge1xuICAgIHRoaXMuZm9yRWFjaE9ic2VydmVyKChvYnNlcnZlcjogT2JzZXJ2ZXI8VD4pID0+IHtcbiAgICAgIG9ic2VydmVyLm5leHQodmFsdWUpO1xuICAgIH0pO1xuICB9XG5cbiAgZXJyb3IoZXJyb3I6IEVycm9yKTogdm9pZCB7XG4gICAgdGhpcy5mb3JFYWNoT2JzZXJ2ZXIoKG9ic2VydmVyOiBPYnNlcnZlcjxUPikgPT4ge1xuICAgICAgb2JzZXJ2ZXIuZXJyb3IoZXJyb3IpO1xuICAgIH0pO1xuICAgIHRoaXMuY2xvc2UoZXJyb3IpO1xuICB9XG5cbiAgY29tcGxldGUoKTogdm9pZCB7XG4gICAgdGhpcy5mb3JFYWNoT2JzZXJ2ZXIoKG9ic2VydmVyOiBPYnNlcnZlcjxUPikgPT4ge1xuICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICB9KTtcbiAgICB0aGlzLmNsb3NlKCk7XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlIGZ1bmN0aW9uIHRoYXQgY2FuIGJlIHVzZWQgdG8gYWRkIGFuIE9ic2VydmVyIHRvIHRoZSBmYW4tb3V0IGxpc3QuXG4gICAqXG4gICAqIC0gV2UgcmVxdWlyZSB0aGF0IG5vIGV2ZW50IGlzIHNlbnQgdG8gYSBzdWJzY3JpYmVyIHN5bmNocm9ub3VzbHkgdG8gdGhlaXJcbiAgICogICBjYWxsIHRvIHN1YnNjcmliZSgpLlxuICAgKi9cbiAgc3Vic2NyaWJlKFxuICAgIG5leHRPck9ic2VydmVyPzogTmV4dEZuPFQ+IHwgUGFydGlhbE9ic2VydmVyPFQ+LFxuICAgIGVycm9yPzogRXJyb3JGbixcbiAgICBjb21wbGV0ZT86IENvbXBsZXRlRm5cbiAgKTogVW5zdWJzY3JpYmUge1xuICAgIGxldCBvYnNlcnZlcjogT2JzZXJ2ZXI8VD47XG5cbiAgICBpZiAoXG4gICAgICBuZXh0T3JPYnNlcnZlciA9PT0gdW5kZWZpbmVkICYmXG4gICAgICBlcnJvciA9PT0gdW5kZWZpbmVkICYmXG4gICAgICBjb21wbGV0ZSA9PT0gdW5kZWZpbmVkXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgT2JzZXJ2ZXIuJyk7XG4gICAgfVxuXG4gICAgLy8gQXNzZW1ibGUgYW4gT2JzZXJ2ZXIgb2JqZWN0IHdoZW4gcGFzc2VkIGFzIGNhbGxiYWNrIGZ1bmN0aW9ucy5cbiAgICBpZiAoXG4gICAgICBpbXBsZW1lbnRzQW55TWV0aG9kcyhuZXh0T3JPYnNlcnZlciBhcyB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfSwgW1xuICAgICAgICAnbmV4dCcsXG4gICAgICAgICdlcnJvcicsXG4gICAgICAgICdjb21wbGV0ZSdcbiAgICAgIF0pXG4gICAgKSB7XG4gICAgICBvYnNlcnZlciA9IG5leHRPck9ic2VydmVyIGFzIE9ic2VydmVyPFQ+O1xuICAgIH0gZWxzZSB7XG4gICAgICBvYnNlcnZlciA9IHtcbiAgICAgICAgbmV4dDogbmV4dE9yT2JzZXJ2ZXIgYXMgTmV4dEZuPFQ+LFxuICAgICAgICBlcnJvcixcbiAgICAgICAgY29tcGxldGVcbiAgICAgIH0gYXMgT2JzZXJ2ZXI8VD47XG4gICAgfVxuXG4gICAgaWYgKG9ic2VydmVyLm5leHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgb2JzZXJ2ZXIubmV4dCA9IG5vb3AgYXMgTmV4dEZuPFQ+O1xuICAgIH1cbiAgICBpZiAob2JzZXJ2ZXIuZXJyb3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgb2JzZXJ2ZXIuZXJyb3IgPSBub29wIGFzIEVycm9yRm47XG4gICAgfVxuICAgIGlmIChvYnNlcnZlci5jb21wbGV0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBvYnNlcnZlci5jb21wbGV0ZSA9IG5vb3AgYXMgQ29tcGxldGVGbjtcbiAgICB9XG5cbiAgICBjb25zdCB1bnN1YiA9IHRoaXMudW5zdWJzY3JpYmVPbmUuYmluZCh0aGlzLCB0aGlzLm9ic2VydmVycyEubGVuZ3RoKTtcblxuICAgIC8vIEF0dGVtcHQgdG8gc3Vic2NyaWJlIHRvIGEgdGVybWluYXRlZCBPYnNlcnZhYmxlIC0gd2VcbiAgICAvLyBqdXN0IHJlc3BvbmQgdG8gdGhlIE9ic2VydmVyIHdpdGggdGhlIGZpbmFsIGVycm9yIG9yIGNvbXBsZXRlXG4gICAgLy8gZXZlbnQuXG4gICAgaWYgKHRoaXMuZmluYWxpemVkKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgICB0aGlzLnRhc2sudGhlbigoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKHRoaXMuZmluYWxFcnJvcikge1xuICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IodGhpcy5maW5hbEVycm9yKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyBub3RoaW5nXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5vYnNlcnZlcnMhLnB1c2gob2JzZXJ2ZXIgYXMgT2JzZXJ2ZXI8VD4pO1xuXG4gICAgcmV0dXJuIHVuc3ViO1xuICB9XG5cbiAgLy8gVW5zdWJzY3JpYmUgaXMgc3luY2hyb25vdXMgLSB3ZSBndWFyYW50ZWUgdGhhdCBubyBldmVudHMgYXJlIHNlbnQgdG9cbiAgLy8gYW55IHVuc3Vic2NyaWJlZCBPYnNlcnZlci5cbiAgcHJpdmF0ZSB1bnN1YnNjcmliZU9uZShpOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5vYnNlcnZlcnMgPT09IHVuZGVmaW5lZCB8fCB0aGlzLm9ic2VydmVyc1tpXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZGVsZXRlIHRoaXMub2JzZXJ2ZXJzW2ldO1xuXG4gICAgdGhpcy5vYnNlcnZlckNvdW50IC09IDE7XG4gICAgaWYgKHRoaXMub2JzZXJ2ZXJDb3VudCA9PT0gMCAmJiB0aGlzLm9uTm9PYnNlcnZlcnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5vbk5vT2JzZXJ2ZXJzKHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZm9yRWFjaE9ic2VydmVyKGZuOiAob2JzZXJ2ZXI6IE9ic2VydmVyPFQ+KSA9PiB2b2lkKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmluYWxpemVkKSB7XG4gICAgICAvLyBBbHJlYWR5IGNsb3NlZCBieSBwcmV2aW91cyBldmVudC4uLi5qdXN0IGVhdCB0aGUgYWRkaXRpb25hbCB2YWx1ZXMuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gU2luY2Ugc2VuZE9uZSBjYWxscyBhc3luY2hyb25vdXNseSAtIHRoZXJlIGlzIG5vIGNoYW5jZSB0aGF0XG4gICAgLy8gdGhpcy5vYnNlcnZlcnMgd2lsbCBiZWNvbWUgdW5kZWZpbmVkLlxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5vYnNlcnZlcnMhLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLnNlbmRPbmUoaSwgZm4pO1xuICAgIH1cbiAgfVxuXG4gIC8vIENhbGwgdGhlIE9ic2VydmVyIHZpYSBvbmUgb2YgaXQncyBjYWxsYmFjayBmdW5jdGlvbi4gV2UgYXJlIGNhcmVmdWwgdG9cbiAgLy8gY29uZmlybSB0aGF0IHRoZSBvYnNlcnZlIGhhcyBub3QgYmVlbiB1bnN1YnNjcmliZWQgc2luY2UgdGhpcyBhc3luY2hyb25vdXNcbiAgLy8gZnVuY3Rpb24gaGFkIGJlZW4gcXVldWVkLlxuICBwcml2YXRlIHNlbmRPbmUoaTogbnVtYmVyLCBmbjogKG9ic2VydmVyOiBPYnNlcnZlcjxUPikgPT4gdm9pZCk6IHZvaWQge1xuICAgIC8vIEV4ZWN1dGUgdGhlIGNhbGxiYWNrIGFzeW5jaHJvbm91c2x5XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICAgIHRoaXMudGFzay50aGVuKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLm9ic2VydmVycyAhPT0gdW5kZWZpbmVkICYmIHRoaXMub2JzZXJ2ZXJzW2ldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmbih0aGlzLm9ic2VydmVyc1tpXSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyBJZ25vcmUgZXhjZXB0aW9ucyByYWlzZWQgaW4gT2JzZXJ2ZXJzIG9yIG1pc3NpbmcgbWV0aG9kcyBvZiBhblxuICAgICAgICAgIC8vIE9ic2VydmVyLlxuICAgICAgICAgIC8vIExvZyBlcnJvciB0byBjb25zb2xlLiBiLzMxNDA0ODA2XG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiBjb25zb2xlLmVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBjbG9zZShlcnI/OiBFcnJvcik6IHZvaWQge1xuICAgIGlmICh0aGlzLmZpbmFsaXplZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmZpbmFsaXplZCA9IHRydWU7XG4gICAgaWYgKGVyciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmZpbmFsRXJyb3IgPSBlcnI7XG4gICAgfVxuICAgIC8vIFByb3h5IGlzIG5vIGxvbmdlciBuZWVkZWQgLSBnYXJiYWdlIGNvbGxlY3QgcmVmZXJlbmNlc1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZmxvYXRpbmctcHJvbWlzZXNcbiAgICB0aGlzLnRhc2sudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLm9ic2VydmVycyA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMub25Ob09ic2VydmVycyA9IHVuZGVmaW5lZDtcbiAgICB9KTtcbiAgfVxufVxuXG4vKiogVHVybiBzeW5jaHJvbm91cyBmdW5jdGlvbiBpbnRvIG9uZSBjYWxsZWQgYXN5bmNocm9ub3VzbHkuICovXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xuZXhwb3J0IGZ1bmN0aW9uIGFzeW5jKGZuOiBGdW5jdGlvbiwgb25FcnJvcj86IEVycm9yRm4pOiBGdW5jdGlvbiB7XG4gIHJldHVybiAoLi4uYXJnczogdW5rbm93bltdKSA9PiB7XG4gICAgUHJvbWlzZS5yZXNvbHZlKHRydWUpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGZuKC4uLmFyZ3MpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmIChvbkVycm9yKSB7XG4gICAgICAgICAgb25FcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9O1xufVxuXG4vKipcbiAqIFJldHVybiB0cnVlIGlmIHRoZSBvYmplY3QgcGFzc2VkIGluIGltcGxlbWVudHMgYW55IG9mIHRoZSBuYW1lZCBtZXRob2RzLlxuICovXG5mdW5jdGlvbiBpbXBsZW1lbnRzQW55TWV0aG9kcyhcbiAgb2JqOiB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfSxcbiAgbWV0aG9kczogc3RyaW5nW11cbik6IGJvb2xlYW4ge1xuICBpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgfHwgb2JqID09PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZm9yIChjb25zdCBtZXRob2Qgb2YgbWV0aG9kcykge1xuICAgIGlmIChtZXRob2QgaW4gb2JqICYmIHR5cGVvZiBvYmpbbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBub29wKCk6IHZvaWQge1xuICAvLyBkbyBub3RoaW5nXG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBDaGVjayB0byBtYWtlIHN1cmUgdGhlIGFwcHJvcHJpYXRlIG51bWJlciBvZiBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIGZvciBhIHB1YmxpYyBmdW5jdGlvbi5cbiAqIFRocm93cyBhbiBlcnJvciBpZiBpdCBmYWlscy5cbiAqXG4gKiBAcGFyYW0gZm5OYW1lIFRoZSBmdW5jdGlvbiBuYW1lXG4gKiBAcGFyYW0gbWluQ291bnQgVGhlIG1pbmltdW0gbnVtYmVyIG9mIGFyZ3VtZW50cyB0byBhbGxvdyBmb3IgdGhlIGZ1bmN0aW9uIGNhbGxcbiAqIEBwYXJhbSBtYXhDb3VudCBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXJndW1lbnQgdG8gYWxsb3cgZm9yIHRoZSBmdW5jdGlvbiBjYWxsXG4gKiBAcGFyYW0gYXJnQ291bnQgVGhlIGFjdHVhbCBudW1iZXIgb2YgYXJndW1lbnRzIHByb3ZpZGVkLlxuICovXG5leHBvcnQgY29uc3QgdmFsaWRhdGVBcmdDb3VudCA9IGZ1bmN0aW9uIChcbiAgZm5OYW1lOiBzdHJpbmcsXG4gIG1pbkNvdW50OiBudW1iZXIsXG4gIG1heENvdW50OiBudW1iZXIsXG4gIGFyZ0NvdW50OiBudW1iZXJcbik6IHZvaWQge1xuICBsZXQgYXJnRXJyb3I7XG4gIGlmIChhcmdDb3VudCA8IG1pbkNvdW50KSB7XG4gICAgYXJnRXJyb3IgPSAnYXQgbGVhc3QgJyArIG1pbkNvdW50O1xuICB9IGVsc2UgaWYgKGFyZ0NvdW50ID4gbWF4Q291bnQpIHtcbiAgICBhcmdFcnJvciA9IG1heENvdW50ID09PSAwID8gJ25vbmUnIDogJ25vIG1vcmUgdGhhbiAnICsgbWF4Q291bnQ7XG4gIH1cbiAgaWYgKGFyZ0Vycm9yKSB7XG4gICAgY29uc3QgZXJyb3IgPVxuICAgICAgZm5OYW1lICtcbiAgICAgICcgZmFpbGVkOiBXYXMgY2FsbGVkIHdpdGggJyArXG4gICAgICBhcmdDb3VudCArXG4gICAgICAoYXJnQ291bnQgPT09IDEgPyAnIGFyZ3VtZW50LicgOiAnIGFyZ3VtZW50cy4nKSArXG4gICAgICAnIEV4cGVjdHMgJyArXG4gICAgICBhcmdFcnJvciArXG4gICAgICAnLic7XG4gICAgdGhyb3cgbmV3IEVycm9yKGVycm9yKTtcbiAgfVxufTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBzdHJpbmcgdG8gcHJlZml4IGFuIGVycm9yIG1lc3NhZ2UgYWJvdXQgZmFpbGVkIGFyZ3VtZW50IHZhbGlkYXRpb25cbiAqXG4gKiBAcGFyYW0gZm5OYW1lIFRoZSBmdW5jdGlvbiBuYW1lXG4gKiBAcGFyYW0gYXJnTmFtZSBUaGUgbmFtZSBvZiB0aGUgYXJndW1lbnRcbiAqIEByZXR1cm4gVGhlIHByZWZpeCB0byBhZGQgdG8gdGhlIGVycm9yIHRocm93biBmb3IgdmFsaWRhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVycm9yUHJlZml4KGZuTmFtZTogc3RyaW5nLCBhcmdOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7Zm5OYW1lfSBmYWlsZWQ6ICR7YXJnTmFtZX0gYXJndW1lbnQgYDtcbn1cblxuLyoqXG4gKiBAcGFyYW0gZm5OYW1lXG4gKiBAcGFyYW0gYXJndW1lbnROdW1iZXJcbiAqIEBwYXJhbSBuYW1lc3BhY2VcbiAqIEBwYXJhbSBvcHRpb25hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVOYW1lc3BhY2UoXG4gIGZuTmFtZTogc3RyaW5nLFxuICBuYW1lc3BhY2U6IHN0cmluZyxcbiAgb3B0aW9uYWw6IGJvb2xlYW5cbik6IHZvaWQge1xuICBpZiAob3B0aW9uYWwgJiYgIW5hbWVzcGFjZSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAodHlwZW9mIG5hbWVzcGFjZSAhPT0gJ3N0cmluZycpIHtcbiAgICAvL1RPRE86IEkgc2hvdWxkIGRvIG1vcmUgdmFsaWRhdGlvbiBoZXJlLiBXZSBvbmx5IGFsbG93IGNlcnRhaW4gY2hhcnMgaW4gbmFtZXNwYWNlcy5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBlcnJvclByZWZpeChmbk5hbWUsICduYW1lc3BhY2UnKSArICdtdXN0IGJlIGEgdmFsaWQgZmlyZWJhc2UgbmFtZXNwYWNlLidcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUNhbGxiYWNrKFxuICBmbk5hbWU6IHN0cmluZyxcbiAgYXJndW1lbnROYW1lOiBzdHJpbmcsXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXR5cGVzXG4gIGNhbGxiYWNrOiBGdW5jdGlvbixcbiAgb3B0aW9uYWw6IGJvb2xlYW5cbik6IHZvaWQge1xuICBpZiAob3B0aW9uYWwgJiYgIWNhbGxiYWNrKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBlcnJvclByZWZpeChmbk5hbWUsIGFyZ3VtZW50TmFtZSkgKyAnbXVzdCBiZSBhIHZhbGlkIGZ1bmN0aW9uLidcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUNvbnRleHRPYmplY3QoXG4gIGZuTmFtZTogc3RyaW5nLFxuICBhcmd1bWVudE5hbWU6IHN0cmluZyxcbiAgY29udGV4dDogdW5rbm93bixcbiAgb3B0aW9uYWw6IGJvb2xlYW5cbik6IHZvaWQge1xuICBpZiAob3B0aW9uYWwgJiYgIWNvbnRleHQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHR5cGVvZiBjb250ZXh0ICE9PSAnb2JqZWN0JyB8fCBjb250ZXh0ID09PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgZXJyb3JQcmVmaXgoZm5OYW1lLCBhcmd1bWVudE5hbWUpICsgJ211c3QgYmUgYSB2YWxpZCBjb250ZXh0IG9iamVjdC4nXG4gICAgKTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4vYXNzZXJ0JztcblxuLy8gQ29kZSBvcmlnaW5hbGx5IGNhbWUgZnJvbSBnb29nLmNyeXB0LnN0cmluZ1RvVXRmOEJ5dGVBcnJheSwgYnV0IGZvciBzb21lIHJlYXNvbiB0aGV5XG4vLyBhdXRvbWF0aWNhbGx5IHJlcGxhY2VkICdcXHJcXG4nIHdpdGggJ1xcbicsIGFuZCB0aGV5IGRpZG4ndCBoYW5kbGUgc3Vycm9nYXRlIHBhaXJzLFxuLy8gc28gaXQncyBiZWVuIG1vZGlmaWVkLlxuXG4vLyBOb3RlIHRoYXQgbm90IGFsbCBVbmljb2RlIGNoYXJhY3RlcnMgYXBwZWFyIGFzIHNpbmdsZSBjaGFyYWN0ZXJzIGluIEphdmFTY3JpcHQgc3RyaW5ncy5cbi8vIGZyb21DaGFyQ29kZSByZXR1cm5zIHRoZSBVVEYtMTYgZW5jb2Rpbmcgb2YgYSBjaGFyYWN0ZXIgLSBzbyBzb21lIFVuaWNvZGUgY2hhcmFjdGVyc1xuLy8gdXNlIDIgY2hhcmFjdGVycyBpbiBKYXZhU2NyaXB0LiAgQWxsIDQtYnl0ZSBVVEYtOCBjaGFyYWN0ZXJzIGJlZ2luIHdpdGggYSBmaXJzdFxuLy8gY2hhcmFjdGVyIGluIHRoZSByYW5nZSAweEQ4MDAgLSAweERCRkYgKHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgYSBzby1jYWxsZWQgc3Vycm9nYXRlXG4vLyBwYWlyKS5cbi8vIFNlZSBodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNS4xLyNzZWMtMTUuMS4zXG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbmV4cG9ydCBjb25zdCBzdHJpbmdUb0J5dGVBcnJheSA9IGZ1bmN0aW9uIChzdHI6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgY29uc3Qgb3V0OiBudW1iZXJbXSA9IFtdO1xuICBsZXQgcCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGMgPSBzdHIuY2hhckNvZGVBdChpKTtcblxuICAgIC8vIElzIHRoaXMgdGhlIGxlYWQgc3Vycm9nYXRlIGluIGEgc3Vycm9nYXRlIHBhaXI/XG4gICAgaWYgKGMgPj0gMHhkODAwICYmIGMgPD0gMHhkYmZmKSB7XG4gICAgICBjb25zdCBoaWdoID0gYyAtIDB4ZDgwMDsgLy8gdGhlIGhpZ2ggMTAgYml0cy5cbiAgICAgIGkrKztcbiAgICAgIGFzc2VydChpIDwgc3RyLmxlbmd0aCwgJ1N1cnJvZ2F0ZSBwYWlyIG1pc3NpbmcgdHJhaWwgc3Vycm9nYXRlLicpO1xuICAgICAgY29uc3QgbG93ID0gc3RyLmNoYXJDb2RlQXQoaSkgLSAweGRjMDA7IC8vIHRoZSBsb3cgMTAgYml0cy5cbiAgICAgIGMgPSAweDEwMDAwICsgKGhpZ2ggPDwgMTApICsgbG93O1xuICAgIH1cblxuICAgIGlmIChjIDwgMTI4KSB7XG4gICAgICBvdXRbcCsrXSA9IGM7XG4gICAgfSBlbHNlIGlmIChjIDwgMjA0OCkge1xuICAgICAgb3V0W3ArK10gPSAoYyA+PiA2KSB8IDE5MjtcbiAgICAgIG91dFtwKytdID0gKGMgJiA2MykgfCAxMjg7XG4gICAgfSBlbHNlIGlmIChjIDwgNjU1MzYpIHtcbiAgICAgIG91dFtwKytdID0gKGMgPj4gMTIpIHwgMjI0O1xuICAgICAgb3V0W3ArK10gPSAoKGMgPj4gNikgJiA2MykgfCAxMjg7XG4gICAgICBvdXRbcCsrXSA9IChjICYgNjMpIHwgMTI4O1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXRbcCsrXSA9IChjID4+IDE4KSB8IDI0MDtcbiAgICAgIG91dFtwKytdID0gKChjID4+IDEyKSAmIDYzKSB8IDEyODtcbiAgICAgIG91dFtwKytdID0gKChjID4+IDYpICYgNjMpIHwgMTI4O1xuICAgICAgb3V0W3ArK10gPSAoYyAmIDYzKSB8IDEyODtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlIGxlbmd0aCB3aXRob3V0IGFjdHVhbGx5IGNvbnZlcnRpbmc7IHVzZWZ1bCBmb3IgZG9pbmcgY2hlYXBlciB2YWxpZGF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICogQHJldHVybiB7bnVtYmVyfVxuICovXG5leHBvcnQgY29uc3Qgc3RyaW5nTGVuZ3RoID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKTogbnVtYmVyIHtcbiAgbGV0IHAgPSAwO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGMgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgcCsrO1xuICAgIH0gZWxzZSBpZiAoYyA8IDIwNDgpIHtcbiAgICAgIHAgKz0gMjtcbiAgICB9IGVsc2UgaWYgKGMgPj0gMHhkODAwICYmIGMgPD0gMHhkYmZmKSB7XG4gICAgICAvLyBMZWFkIHN1cnJvZ2F0ZSBvZiBhIHN1cnJvZ2F0ZSBwYWlyLiAgVGhlIHBhaXIgdG9nZXRoZXIgd2lsbCB0YWtlIDQgYnl0ZXMgdG8gcmVwcmVzZW50LlxuICAgICAgcCArPSA0O1xuICAgICAgaSsrOyAvLyBza2lwIHRyYWlsIHN1cnJvZ2F0ZS5cbiAgICB9IGVsc2Uge1xuICAgICAgcCArPSAzO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcDtcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBUaGUgYW1vdW50IG9mIG1pbGxpc2Vjb25kcyB0byBleHBvbmVudGlhbGx5IGluY3JlYXNlLlxuICovXG5jb25zdCBERUZBVUxUX0lOVEVSVkFMX01JTExJUyA9IDEwMDA7XG5cbi8qKlxuICogVGhlIGZhY3RvciB0byBiYWNrb2ZmIGJ5LlxuICogU2hvdWxkIGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiAxLlxuICovXG5jb25zdCBERUZBVUxUX0JBQ0tPRkZfRkFDVE9SID0gMjtcblxuLyoqXG4gKiBUaGUgbWF4aW11bSBtaWxsaXNlY29uZHMgdG8gaW5jcmVhc2UgdG8uXG4gKlxuICogPHA+VmlzaWJsZSBmb3IgdGVzdGluZ1xuICovXG5leHBvcnQgY29uc3QgTUFYX1ZBTFVFX01JTExJUyA9IDQgKiA2MCAqIDYwICogMTAwMDsgLy8gRm91ciBob3VycywgbGlrZSBpT1MgYW5kIEFuZHJvaWQuXG5cbi8qKlxuICogVGhlIHBlcmNlbnRhZ2Ugb2YgYmFja29mZiB0aW1lIHRvIHJhbmRvbWl6ZSBieS5cbiAqIFNlZVxuICogaHR0cDovL2dvL3NhZmUtY2xpZW50LWJlaGF2aW9yI3N0ZXAtMS1kZXRlcm1pbmUtdGhlLWFwcHJvcHJpYXRlLXJldHJ5LWludGVydmFsLXRvLWhhbmRsZS1zcGlrZS10cmFmZmljXG4gKiBmb3IgY29udGV4dC5cbiAqXG4gKiA8cD5WaXNpYmxlIGZvciB0ZXN0aW5nXG4gKi9cbmV4cG9ydCBjb25zdCBSQU5ET01fRkFDVE9SID0gMC41O1xuXG4vKipcbiAqIEJhc2VkIG9uIHRoZSBiYWNrb2ZmIG1ldGhvZCBmcm9tXG4gKiBodHRwczovL2dpdGh1Yi5jb20vZ29vZ2xlL2Nsb3N1cmUtbGlicmFyeS9ibG9iL21hc3Rlci9jbG9zdXJlL2dvb2cvbWF0aC9leHBvbmVudGlhbGJhY2tvZmYuanMuXG4gKiBFeHRyYWN0ZWQgaGVyZSBzbyB3ZSBkb24ndCBuZWVkIHRvIHBhc3MgbWV0YWRhdGEgYW5kIGEgc3RhdGVmdWwgRXhwb25lbnRpYWxCYWNrb2ZmIG9iamVjdCBhcm91bmQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVCYWNrb2ZmTWlsbGlzKFxuICBiYWNrb2ZmQ291bnQ6IG51bWJlcixcbiAgaW50ZXJ2YWxNaWxsaXM6IG51bWJlciA9IERFRkFVTFRfSU5URVJWQUxfTUlMTElTLFxuICBiYWNrb2ZmRmFjdG9yOiBudW1iZXIgPSBERUZBVUxUX0JBQ0tPRkZfRkFDVE9SXG4pOiBudW1iZXIge1xuICAvLyBDYWxjdWxhdGVzIGFuIGV4cG9uZW50aWFsbHkgaW5jcmVhc2luZyB2YWx1ZS5cbiAgLy8gRGV2aWF0aW9uOiBjYWxjdWxhdGVzIHZhbHVlIGZyb20gY291bnQgYW5kIGEgY29uc3RhbnQgaW50ZXJ2YWwsIHNvIHdlIG9ubHkgbmVlZCB0byBzYXZlIHZhbHVlXG4gIC8vIGFuZCBjb3VudCB0byByZXN0b3JlIHN0YXRlLlxuICBjb25zdCBjdXJyQmFzZVZhbHVlID0gaW50ZXJ2YWxNaWxsaXMgKiBNYXRoLnBvdyhiYWNrb2ZmRmFjdG9yLCBiYWNrb2ZmQ291bnQpO1xuXG4gIC8vIEEgcmFuZG9tIFwiZnV6elwiIHRvIGF2b2lkIHdhdmVzIG9mIHJldHJpZXMuXG4gIC8vIERldmlhdGlvbjogcmFuZG9tRmFjdG9yIGlzIHJlcXVpcmVkLlxuICBjb25zdCByYW5kb21XYWl0ID0gTWF0aC5yb3VuZChcbiAgICAvLyBBIGZyYWN0aW9uIG9mIHRoZSBiYWNrb2ZmIHZhbHVlIHRvIGFkZC9zdWJ0cmFjdC5cbiAgICAvLyBEZXZpYXRpb246IGNoYW5nZXMgbXVsdGlwbGljYXRpb24gb3JkZXIgdG8gaW1wcm92ZSByZWFkYWJpbGl0eS5cbiAgICBSQU5ET01fRkFDVE9SICpcbiAgICAgIGN1cnJCYXNlVmFsdWUgKlxuICAgICAgLy8gQSByYW5kb20gZmxvYXQgKHJvdW5kZWQgdG8gaW50IGJ5IE1hdGgucm91bmQgYWJvdmUpIGluIHRoZSByYW5nZSBbLTEsIDFdLiBEZXRlcm1pbmVzXG4gICAgICAvLyBpZiB3ZSBhZGQgb3Igc3VidHJhY3QuXG4gICAgICAoTWF0aC5yYW5kb20oKSAtIDAuNSkgKlxuICAgICAgMlxuICApO1xuXG4gIC8vIExpbWl0cyBiYWNrb2ZmIHRvIG1heCB0byBhdm9pZCBlZmZlY3RpdmVseSBwZXJtYW5lbnQgYmFja29mZi5cbiAgcmV0dXJuIE1hdGgubWluKE1BWF9WQUxVRV9NSUxMSVMsIGN1cnJCYXNlVmFsdWUgKyByYW5kb21XYWl0KTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIFByb3ZpZGUgRW5nbGlzaCBvcmRpbmFsIGxldHRlcnMgYWZ0ZXIgYSBudW1iZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9yZGluYWwoaTogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoaSkpIHtcbiAgICByZXR1cm4gYCR7aX1gO1xuICB9XG4gIHJldHVybiBpICsgaW5kaWNhdG9yKGkpO1xufVxuXG5mdW5jdGlvbiBpbmRpY2F0b3IoaTogbnVtYmVyKTogc3RyaW5nIHtcbiAgaSA9IE1hdGguYWJzKGkpO1xuICBjb25zdCBjZW50ID0gaSAlIDEwMDtcbiAgaWYgKGNlbnQgPj0gMTAgJiYgY2VudCA8PSAyMCkge1xuICAgIHJldHVybiAndGgnO1xuICB9XG4gIGNvbnN0IGRlYyA9IGkgJSAxMDtcbiAgaWYgKGRlYyA9PT0gMSkge1xuICAgIHJldHVybiAnc3QnO1xuICB9XG4gIGlmIChkZWMgPT09IDIpIHtcbiAgICByZXR1cm4gJ25kJztcbiAgfVxuICBpZiAoZGVjID09PSAzKSB7XG4gICAgcmV0dXJuICdyZCc7XG4gIH1cbiAgcmV0dXJuICd0aCc7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBDb21wYXQ8VD4ge1xuICBfZGVsZWdhdGU6IFQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRNb2R1bGFySW5zdGFuY2U8RXhwU2VydmljZT4oXG4gIHNlcnZpY2U6IENvbXBhdDxFeHBTZXJ2aWNlPiB8IEV4cFNlcnZpY2Vcbik6IEV4cFNlcnZpY2Uge1xuICBpZiAoc2VydmljZSAmJiAoc2VydmljZSBhcyBDb21wYXQ8RXhwU2VydmljZT4pLl9kZWxlZ2F0ZSkge1xuICAgIHJldHVybiAoc2VydmljZSBhcyBDb21wYXQ8RXhwU2VydmljZT4pLl9kZWxlZ2F0ZTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc2VydmljZSBhcyBFeHBTZXJ2aWNlO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQ09OU1RBTlRTIH0gZnJvbSAnLi9zcmMvY29uc3RhbnRzJztcblxuLy8gT3ZlcnJpZGluZyB0aGUgY29uc3RhbnQgKHdlIHNob3VsZCBiZSB0aGUgb25seSBvbmVzIGRvaW5nIHRoaXMpXG5DT05TVEFOVFMuTk9ERV9DTElFTlQgPSB0cnVlO1xuXG5leHBvcnQgKiBmcm9tICcuL3NyYy9hc3NlcnQnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvY3J5cHQnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvY29uc3RhbnRzJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2RlZXBDb3B5JztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2RlZmF1bHRzJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2RlZmVycmVkJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2VtdWxhdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2Vudmlyb25tZW50JztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2Vycm9ycyc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9qc29uJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2p3dCc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9vYmonO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvcHJvbWlzZSc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9xdWVyeSc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9zaGExJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL3N1YnNjcmliZSc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy92YWxpZGF0aW9uJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL3V0ZjgnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvZXhwb25lbnRpYWxfYmFja29mZic7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9mb3JtYXR0ZXJzJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2NvbXBhdCc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9nbG9iYWwnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvdXJsJztcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHtcbiAgSW5zdGFudGlhdGlvbk1vZGUsXG4gIEluc3RhbmNlRmFjdG9yeSxcbiAgQ29tcG9uZW50VHlwZSxcbiAgRGljdGlvbmFyeSxcbiAgTmFtZSxcbiAgb25JbnN0YW5jZUNyZWF0ZWRDYWxsYmFja1xufSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBDb21wb25lbnQgZm9yIHNlcnZpY2UgbmFtZSBULCBlLmcuIGBhdXRoYCwgYGF1dGgtaW50ZXJuYWxgXG4gKi9cbmV4cG9ydCBjbGFzcyBDb21wb25lbnQ8VCBleHRlbmRzIE5hbWUgPSBOYW1lPiB7XG4gIG11bHRpcGxlSW5zdGFuY2VzID0gZmFsc2U7XG4gIC8qKlxuICAgKiBQcm9wZXJ0aWVzIHRvIGJlIGFkZGVkIHRvIHRoZSBzZXJ2aWNlIG5hbWVzcGFjZVxuICAgKi9cbiAgc2VydmljZVByb3BzOiBEaWN0aW9uYXJ5ID0ge307XG5cbiAgaW5zdGFudGlhdGlvbk1vZGUgPSBJbnN0YW50aWF0aW9uTW9kZS5MQVpZO1xuXG4gIG9uSW5zdGFuY2VDcmVhdGVkOiBvbkluc3RhbmNlQ3JlYXRlZENhbGxiYWNrPFQ+IHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIFRoZSBwdWJsaWMgc2VydmljZSBuYW1lLCBlLmcuIGFwcCwgYXV0aCwgZmlyZXN0b3JlLCBkYXRhYmFzZVxuICAgKiBAcGFyYW0gaW5zdGFuY2VGYWN0b3J5IFNlcnZpY2UgZmFjdG9yeSByZXNwb25zaWJsZSBmb3IgY3JlYXRpbmcgdGhlIHB1YmxpYyBpbnRlcmZhY2VcbiAgICogQHBhcmFtIHR5cGUgd2hldGhlciB0aGUgc2VydmljZSBwcm92aWRlZCBieSB0aGUgY29tcG9uZW50IGlzIHB1YmxpYyBvciBwcml2YXRlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBuYW1lOiBULFxuICAgIHJlYWRvbmx5IGluc3RhbmNlRmFjdG9yeTogSW5zdGFuY2VGYWN0b3J5PFQ+LFxuICAgIHJlYWRvbmx5IHR5cGU6IENvbXBvbmVudFR5cGVcbiAgKSB7fVxuXG4gIHNldEluc3RhbnRpYXRpb25Nb2RlKG1vZGU6IEluc3RhbnRpYXRpb25Nb2RlKTogdGhpcyB7XG4gICAgdGhpcy5pbnN0YW50aWF0aW9uTW9kZSA9IG1vZGU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRNdWx0aXBsZUluc3RhbmNlcyhtdWx0aXBsZUluc3RhbmNlczogYm9vbGVhbik6IHRoaXMge1xuICAgIHRoaXMubXVsdGlwbGVJbnN0YW5jZXMgPSBtdWx0aXBsZUluc3RhbmNlcztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHNldFNlcnZpY2VQcm9wcyhwcm9wczogRGljdGlvbmFyeSk6IHRoaXMge1xuICAgIHRoaXMuc2VydmljZVByb3BzID0gcHJvcHM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRJbnN0YW5jZUNyZWF0ZWRDYWxsYmFjayhjYWxsYmFjazogb25JbnN0YW5jZUNyZWF0ZWRDYWxsYmFjazxUPik6IHRoaXMge1xuICAgIHRoaXMub25JbnN0YW5jZUNyZWF0ZWQgPSBjYWxsYmFjaztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0VOVFJZX05BTUUgPSAnW0RFRkFVTFRdJztcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBEZWZlcnJlZCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IENvbXBvbmVudENvbnRhaW5lciB9IGZyb20gJy4vY29tcG9uZW50X2NvbnRhaW5lcic7XG5pbXBvcnQgeyBERUZBVUxUX0VOVFJZX05BTUUgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBJbml0aWFsaXplT3B0aW9ucyxcbiAgSW5zdGFudGlhdGlvbk1vZGUsXG4gIE5hbWUsXG4gIE5hbWVTZXJ2aWNlTWFwcGluZyxcbiAgT25Jbml0Q2FsbEJhY2tcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudCc7XG5cbi8qKlxuICogUHJvdmlkZXIgZm9yIGluc3RhbmNlIGZvciBzZXJ2aWNlIG5hbWUgVCwgZS5nLiAnYXV0aCcsICdhdXRoLWludGVybmFsJ1xuICogTmFtZVNlcnZpY2VNYXBwaW5nW1RdIGlzIGFuIGFsaWFzIGZvciB0aGUgdHlwZSBvZiB0aGUgaW5zdGFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIFByb3ZpZGVyPFQgZXh0ZW5kcyBOYW1lPiB7XG4gIHByaXZhdGUgY29tcG9uZW50OiBDb21wb25lbnQ8VD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnN0YW5jZXM6IE1hcDxzdHJpbmcsIE5hbWVTZXJ2aWNlTWFwcGluZ1tUXT4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5zdGFuY2VzRGVmZXJyZWQ6IE1hcDxcbiAgICBzdHJpbmcsXG4gICAgRGVmZXJyZWQ8TmFtZVNlcnZpY2VNYXBwaW5nW1RdPlxuICA+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGluc3RhbmNlc09wdGlvbnM6IE1hcDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHVua25vd24+PiA9XG4gICAgbmV3IE1hcCgpO1xuICBwcml2YXRlIG9uSW5pdENhbGxiYWNrczogTWFwPHN0cmluZywgU2V0PE9uSW5pdENhbGxCYWNrPFQ+Pj4gPSBuZXcgTWFwKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBuYW1lOiBULFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29udGFpbmVyOiBDb21wb25lbnRDb250YWluZXJcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gaWRlbnRpZmllciBBIHByb3ZpZGVyIGNhbiBwcm92aWRlIG11bHRpcGxlIGluc3RhbmNlcyBvZiBhIHNlcnZpY2VcbiAgICogaWYgdGhpcy5jb21wb25lbnQubXVsdGlwbGVJbnN0YW5jZXMgaXMgdHJ1ZS5cbiAgICovXG4gIGdldChpZGVudGlmaWVyPzogc3RyaW5nKTogUHJvbWlzZTxOYW1lU2VydmljZU1hcHBpbmdbVF0+IHtcbiAgICAvLyBpZiBtdWx0aXBsZUluc3RhbmNlcyBpcyBub3Qgc3VwcG9ydGVkLCB1c2UgdGhlIGRlZmF1bHQgbmFtZVxuICAgIGNvbnN0IG5vcm1hbGl6ZWRJZGVudGlmaWVyID0gdGhpcy5ub3JtYWxpemVJbnN0YW5jZUlkZW50aWZpZXIoaWRlbnRpZmllcik7XG5cbiAgICBpZiAoIXRoaXMuaW5zdGFuY2VzRGVmZXJyZWQuaGFzKG5vcm1hbGl6ZWRJZGVudGlmaWVyKSkge1xuICAgICAgY29uc3QgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWQ8TmFtZVNlcnZpY2VNYXBwaW5nW1RdPigpO1xuICAgICAgdGhpcy5pbnN0YW5jZXNEZWZlcnJlZC5zZXQobm9ybWFsaXplZElkZW50aWZpZXIsIGRlZmVycmVkKTtcblxuICAgICAgaWYgKFxuICAgICAgICB0aGlzLmlzSW5pdGlhbGl6ZWQobm9ybWFsaXplZElkZW50aWZpZXIpIHx8XG4gICAgICAgIHRoaXMuc2hvdWxkQXV0b0luaXRpYWxpemUoKVxuICAgICAgKSB7XG4gICAgICAgIC8vIGluaXRpYWxpemUgdGhlIHNlcnZpY2UgaWYgaXQgY2FuIGJlIGF1dG8taW5pdGlhbGl6ZWRcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBpbnN0YW5jZSA9IHRoaXMuZ2V0T3JJbml0aWFsaXplU2VydmljZSh7XG4gICAgICAgICAgICBpbnN0YW5jZUlkZW50aWZpZXI6IG5vcm1hbGl6ZWRJZGVudGlmaWVyXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKGluc3RhbmNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyB3aGVuIHRoZSBpbnN0YW5jZSBmYWN0b3J5IHRocm93cyBhbiBleGNlcHRpb24gZHVyaW5nIGdldCgpLCBpdCBzaG91bGQgbm90IGNhdXNlXG4gICAgICAgICAgLy8gYSBmYXRhbCBlcnJvci4gV2UganVzdCByZXR1cm4gdGhlIHVucmVzb2x2ZWQgcHJvbWlzZSBpbiB0aGlzIGNhc2UuXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pbnN0YW5jZXNEZWZlcnJlZC5nZXQobm9ybWFsaXplZElkZW50aWZpZXIpIS5wcm9taXNlO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSBvcHRpb25zLmlkZW50aWZpZXIgQSBwcm92aWRlciBjYW4gcHJvdmlkZSBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgYSBzZXJ2aWNlXG4gICAqIGlmIHRoaXMuY29tcG9uZW50Lm11bHRpcGxlSW5zdGFuY2VzIGlzIHRydWUuXG4gICAqIEBwYXJhbSBvcHRpb25zLm9wdGlvbmFsIElmIG9wdGlvbmFsIGlzIGZhbHNlIG9yIG5vdCBwcm92aWRlZCwgdGhlIG1ldGhvZCB0aHJvd3MgYW4gZXJyb3Igd2hlblxuICAgKiB0aGUgc2VydmljZSBpcyBub3QgaW1tZWRpYXRlbHkgYXZhaWxhYmxlLlxuICAgKiBJZiBvcHRpb25hbCBpcyB0cnVlLCB0aGUgbWV0aG9kIHJldHVybnMgbnVsbCBpZiB0aGUgc2VydmljZSBpcyBub3QgaW1tZWRpYXRlbHkgYXZhaWxhYmxlLlxuICAgKi9cbiAgZ2V0SW1tZWRpYXRlKG9wdGlvbnM6IHtcbiAgICBpZGVudGlmaWVyPzogc3RyaW5nO1xuICAgIG9wdGlvbmFsOiB0cnVlO1xuICB9KTogTmFtZVNlcnZpY2VNYXBwaW5nW1RdIHwgbnVsbDtcbiAgZ2V0SW1tZWRpYXRlKG9wdGlvbnM/OiB7XG4gICAgaWRlbnRpZmllcj86IHN0cmluZztcbiAgICBvcHRpb25hbD86IGZhbHNlO1xuICB9KTogTmFtZVNlcnZpY2VNYXBwaW5nW1RdO1xuICBnZXRJbW1lZGlhdGUob3B0aW9ucz86IHtcbiAgICBpZGVudGlmaWVyPzogc3RyaW5nO1xuICAgIG9wdGlvbmFsPzogYm9vbGVhbjtcbiAgfSk6IE5hbWVTZXJ2aWNlTWFwcGluZ1tUXSB8IG51bGwge1xuICAgIC8vIGlmIG11bHRpcGxlSW5zdGFuY2VzIGlzIG5vdCBzdXBwb3J0ZWQsIHVzZSB0aGUgZGVmYXVsdCBuYW1lXG4gICAgY29uc3Qgbm9ybWFsaXplZElkZW50aWZpZXIgPSB0aGlzLm5vcm1hbGl6ZUluc3RhbmNlSWRlbnRpZmllcihcbiAgICAgIG9wdGlvbnM/LmlkZW50aWZpZXJcbiAgICApO1xuICAgIGNvbnN0IG9wdGlvbmFsID0gb3B0aW9ucz8ub3B0aW9uYWwgPz8gZmFsc2U7XG5cbiAgICBpZiAoXG4gICAgICB0aGlzLmlzSW5pdGlhbGl6ZWQobm9ybWFsaXplZElkZW50aWZpZXIpIHx8XG4gICAgICB0aGlzLnNob3VsZEF1dG9Jbml0aWFsaXplKClcbiAgICApIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE9ySW5pdGlhbGl6ZVNlcnZpY2Uoe1xuICAgICAgICAgIGluc3RhbmNlSWRlbnRpZmllcjogbm9ybWFsaXplZElkZW50aWZpZXJcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChvcHRpb25hbCkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSW4gY2FzZSBhIGNvbXBvbmVudCBpcyBub3QgaW5pdGlhbGl6ZWQgYW5kIHNob3VsZC9jYW5ub3QgYmUgYXV0by1pbml0aWFsaXplZCBhdCB0aGUgbW9tZW50LCByZXR1cm4gbnVsbCBpZiB0aGUgb3B0aW9uYWwgZmxhZyBpcyBzZXQsIG9yIHRocm93XG4gICAgICBpZiAob3B0aW9uYWwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcihgU2VydmljZSAke3RoaXMubmFtZX0gaXMgbm90IGF2YWlsYWJsZWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldENvbXBvbmVudCgpOiBDb21wb25lbnQ8VD4gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnQ7XG4gIH1cblxuICBzZXRDb21wb25lbnQoY29tcG9uZW50OiBDb21wb25lbnQ8VD4pOiB2b2lkIHtcbiAgICBpZiAoY29tcG9uZW50Lm5hbWUgIT09IHRoaXMubmFtZSkge1xuICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgIGBNaXNtYXRjaGluZyBDb21wb25lbnQgJHtjb21wb25lbnQubmFtZX0gZm9yIFByb3ZpZGVyICR7dGhpcy5uYW1lfS5gXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbXBvbmVudCkge1xuICAgICAgdGhyb3cgRXJyb3IoYENvbXBvbmVudCBmb3IgJHt0aGlzLm5hbWV9IGhhcyBhbHJlYWR5IGJlZW4gcHJvdmlkZWRgKTtcbiAgICB9XG5cbiAgICB0aGlzLmNvbXBvbmVudCA9IGNvbXBvbmVudDtcblxuICAgIC8vIHJldHVybiBlYXJseSB3aXRob3V0IGF0dGVtcHRpbmcgdG8gaW5pdGlhbGl6ZSB0aGUgY29tcG9uZW50IGlmIHRoZSBjb21wb25lbnQgcmVxdWlyZXMgZXhwbGljaXQgaW5pdGlhbGl6YXRpb24gKGNhbGxpbmcgYFByb3ZpZGVyLmluaXRpYWxpemUoKWApXG4gICAgaWYgKCF0aGlzLnNob3VsZEF1dG9Jbml0aWFsaXplKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgc2VydmljZSBpcyBlYWdlciwgaW5pdGlhbGl6ZSB0aGUgZGVmYXVsdCBpbnN0YW5jZVxuICAgIGlmIChpc0NvbXBvbmVudEVhZ2VyKGNvbXBvbmVudCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuZ2V0T3JJbml0aWFsaXplU2VydmljZSh7IGluc3RhbmNlSWRlbnRpZmllcjogREVGQVVMVF9FTlRSWV9OQU1FIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyB3aGVuIHRoZSBpbnN0YW5jZSBmYWN0b3J5IGZvciBhbiBlYWdlciBDb21wb25lbnQgdGhyb3dzIGFuIGV4Y2VwdGlvbiBkdXJpbmcgdGhlIGVhZ2VyXG4gICAgICAgIC8vIGluaXRpYWxpemF0aW9uLCBpdCBzaG91bGQgbm90IGNhdXNlIGEgZmF0YWwgZXJyb3IuXG4gICAgICAgIC8vIFRPRE86IEludmVzdGlnYXRlIGlmIHdlIG5lZWQgdG8gbWFrZSBpdCBjb25maWd1cmFibGUsIGJlY2F1c2Ugc29tZSBjb21wb25lbnQgbWF5IHdhbnQgdG8gY2F1c2VcbiAgICAgICAgLy8gYSBmYXRhbCBlcnJvciBpbiB0aGlzIGNhc2U/XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIHNlcnZpY2UgaW5zdGFuY2VzIGZvciB0aGUgcGVuZGluZyBwcm9taXNlcyBhbmQgcmVzb2x2ZSB0aGVtXG4gICAgLy8gTk9URTogaWYgdGhpcy5tdWx0aXBsZUluc3RhbmNlcyBpcyBmYWxzZSwgb25seSB0aGUgZGVmYXVsdCBpbnN0YW5jZSB3aWxsIGJlIGNyZWF0ZWRcbiAgICAvLyBhbmQgYWxsIHByb21pc2VzIHdpdGggcmVzb2x2ZSB3aXRoIGl0IHJlZ2FyZGxlc3Mgb2YgdGhlIGlkZW50aWZpZXIuXG4gICAgZm9yIChjb25zdCBbXG4gICAgICBpbnN0YW5jZUlkZW50aWZpZXIsXG4gICAgICBpbnN0YW5jZURlZmVycmVkXG4gICAgXSBvZiB0aGlzLmluc3RhbmNlc0RlZmVycmVkLmVudHJpZXMoKSkge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZElkZW50aWZpZXIgPVxuICAgICAgICB0aGlzLm5vcm1hbGl6ZUluc3RhbmNlSWRlbnRpZmllcihpbnN0YW5jZUlkZW50aWZpZXIpO1xuXG4gICAgICB0cnkge1xuICAgICAgICAvLyBgZ2V0T3JJbml0aWFsaXplU2VydmljZSgpYCBzaG91bGQgYWx3YXlzIHJldHVybiBhIHZhbGlkIGluc3RhbmNlIHNpbmNlIGEgY29tcG9uZW50IGlzIGd1YXJhbnRlZWQuIHVzZSAhIHRvIG1ha2UgdHlwZXNjcmlwdCBoYXBweS5cbiAgICAgICAgY29uc3QgaW5zdGFuY2UgPSB0aGlzLmdldE9ySW5pdGlhbGl6ZVNlcnZpY2Uoe1xuICAgICAgICAgIGluc3RhbmNlSWRlbnRpZmllcjogbm9ybWFsaXplZElkZW50aWZpZXJcbiAgICAgICAgfSkhO1xuICAgICAgICBpbnN0YW5jZURlZmVycmVkLnJlc29sdmUoaW5zdGFuY2UpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyB3aGVuIHRoZSBpbnN0YW5jZSBmYWN0b3J5IHRocm93cyBhbiBleGNlcHRpb24sIGl0IHNob3VsZCBub3QgY2F1c2VcbiAgICAgICAgLy8gYSBmYXRhbCBlcnJvci4gV2UganVzdCBsZWF2ZSB0aGUgcHJvbWlzZSB1bnJlc29sdmVkLlxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNsZWFySW5zdGFuY2UoaWRlbnRpZmllcjogc3RyaW5nID0gREVGQVVMVF9FTlRSWV9OQU1FKTogdm9pZCB7XG4gICAgdGhpcy5pbnN0YW5jZXNEZWZlcnJlZC5kZWxldGUoaWRlbnRpZmllcik7XG4gICAgdGhpcy5pbnN0YW5jZXNPcHRpb25zLmRlbGV0ZShpZGVudGlmaWVyKTtcbiAgICB0aGlzLmluc3RhbmNlcy5kZWxldGUoaWRlbnRpZmllcik7XG4gIH1cblxuICAvLyBhcHAuZGVsZXRlKCkgd2lsbCBjYWxsIHRoaXMgbWV0aG9kIG9uIGV2ZXJ5IHByb3ZpZGVyIHRvIGRlbGV0ZSB0aGUgc2VydmljZXNcbiAgLy8gVE9ETzogc2hvdWxkIHdlIG1hcmsgdGhlIHByb3ZpZGVyIGFzIGRlbGV0ZWQ/XG4gIGFzeW5jIGRlbGV0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBzZXJ2aWNlcyA9IEFycmF5LmZyb20odGhpcy5pbnN0YW5jZXMudmFsdWVzKCkpO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgLi4uc2VydmljZXNcbiAgICAgICAgLmZpbHRlcihzZXJ2aWNlID0+ICdJTlRFUk5BTCcgaW4gc2VydmljZSkgLy8gbGVnYWN5IHNlcnZpY2VzXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIC5tYXAoc2VydmljZSA9PiAoc2VydmljZSBhcyBhbnkpLklOVEVSTkFMIS5kZWxldGUoKSksXG4gICAgICAuLi5zZXJ2aWNlc1xuICAgICAgICAuZmlsdGVyKHNlcnZpY2UgPT4gJ19kZWxldGUnIGluIHNlcnZpY2UpIC8vIG1vZHVsYXJpemVkIHNlcnZpY2VzXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIC5tYXAoc2VydmljZSA9PiAoc2VydmljZSBhcyBhbnkpLl9kZWxldGUoKSlcbiAgICBdKTtcbiAgfVxuXG4gIGlzQ29tcG9uZW50U2V0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbXBvbmVudCAhPSBudWxsO1xuICB9XG5cbiAgaXNJbml0aWFsaXplZChpZGVudGlmaWVyOiBzdHJpbmcgPSBERUZBVUxUX0VOVFJZX05BTUUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pbnN0YW5jZXMuaGFzKGlkZW50aWZpZXIpO1xuICB9XG5cbiAgZ2V0T3B0aW9ucyhpZGVudGlmaWVyOiBzdHJpbmcgPSBERUZBVUxUX0VOVFJZX05BTUUpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gICAgcmV0dXJuIHRoaXMuaW5zdGFuY2VzT3B0aW9ucy5nZXQoaWRlbnRpZmllcikgfHwge307XG4gIH1cblxuICBpbml0aWFsaXplKG9wdHM6IEluaXRpYWxpemVPcHRpb25zID0ge30pOiBOYW1lU2VydmljZU1hcHBpbmdbVF0ge1xuICAgIGNvbnN0IHsgb3B0aW9ucyA9IHt9IH0gPSBvcHRzO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRJZGVudGlmaWVyID0gdGhpcy5ub3JtYWxpemVJbnN0YW5jZUlkZW50aWZpZXIoXG4gICAgICBvcHRzLmluc3RhbmNlSWRlbnRpZmllclxuICAgICk7XG4gICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZChub3JtYWxpemVkSWRlbnRpZmllcikpIHtcbiAgICAgIHRocm93IEVycm9yKFxuICAgICAgICBgJHt0aGlzLm5hbWV9KCR7bm9ybWFsaXplZElkZW50aWZpZXJ9KSBoYXMgYWxyZWFkeSBiZWVuIGluaXRpYWxpemVkYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNDb21wb25lbnRTZXQoKSkge1xuICAgICAgdGhyb3cgRXJyb3IoYENvbXBvbmVudCAke3RoaXMubmFtZX0gaGFzIG5vdCBiZWVuIHJlZ2lzdGVyZWQgeWV0YCk7XG4gICAgfVxuXG4gICAgY29uc3QgaW5zdGFuY2UgPSB0aGlzLmdldE9ySW5pdGlhbGl6ZVNlcnZpY2Uoe1xuICAgICAgaW5zdGFuY2VJZGVudGlmaWVyOiBub3JtYWxpemVkSWRlbnRpZmllcixcbiAgICAgIG9wdGlvbnNcbiAgICB9KSE7XG5cbiAgICAvLyByZXNvbHZlIGFueSBwZW5kaW5nIHByb21pc2Ugd2FpdGluZyBmb3IgdGhlIHNlcnZpY2UgaW5zdGFuY2VcbiAgICBmb3IgKGNvbnN0IFtcbiAgICAgIGluc3RhbmNlSWRlbnRpZmllcixcbiAgICAgIGluc3RhbmNlRGVmZXJyZWRcbiAgICBdIG9mIHRoaXMuaW5zdGFuY2VzRGVmZXJyZWQuZW50cmllcygpKSB7XG4gICAgICBjb25zdCBub3JtYWxpemVkRGVmZXJyZWRJZGVudGlmaWVyID1cbiAgICAgICAgdGhpcy5ub3JtYWxpemVJbnN0YW5jZUlkZW50aWZpZXIoaW5zdGFuY2VJZGVudGlmaWVyKTtcbiAgICAgIGlmIChub3JtYWxpemVkSWRlbnRpZmllciA9PT0gbm9ybWFsaXplZERlZmVycmVkSWRlbnRpZmllcikge1xuICAgICAgICBpbnN0YW5jZURlZmVycmVkLnJlc29sdmUoaW5zdGFuY2UpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBpbnZva2VkICBhZnRlciB0aGUgcHJvdmlkZXIgaGFzIGJlZW4gaW5pdGlhbGl6ZWQgYnkgY2FsbGluZyBwcm92aWRlci5pbml0aWFsaXplKCkuXG4gICAqIFRoZSBmdW5jdGlvbiBpcyBpbnZva2VkIFNZTkNIUk9OT1VTTFksIHNvIGl0IHNob3VsZCBub3QgZXhlY3V0ZSBhbnkgbG9uZ3J1bm5pbmcgdGFza3MgaW4gb3JkZXIgdG8gbm90IGJsb2NrIHRoZSBwcm9ncmFtLlxuICAgKlxuICAgKiBAcGFyYW0gaWRlbnRpZmllciBBbiBvcHRpb25hbCBpbnN0YW5jZSBpZGVudGlmaWVyXG4gICAqIEByZXR1cm5zIGEgZnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGUgY2FsbGJhY2tcbiAgICovXG4gIG9uSW5pdChjYWxsYmFjazogT25Jbml0Q2FsbEJhY2s8VD4sIGlkZW50aWZpZXI/OiBzdHJpbmcpOiAoKSA9PiB2b2lkIHtcbiAgICBjb25zdCBub3JtYWxpemVkSWRlbnRpZmllciA9IHRoaXMubm9ybWFsaXplSW5zdGFuY2VJZGVudGlmaWVyKGlkZW50aWZpZXIpO1xuICAgIGNvbnN0IGV4aXN0aW5nQ2FsbGJhY2tzID1cbiAgICAgIHRoaXMub25Jbml0Q2FsbGJhY2tzLmdldChub3JtYWxpemVkSWRlbnRpZmllcikgPz9cbiAgICAgIG5ldyBTZXQ8T25Jbml0Q2FsbEJhY2s8VD4+KCk7XG4gICAgZXhpc3RpbmdDYWxsYmFja3MuYWRkKGNhbGxiYWNrKTtcbiAgICB0aGlzLm9uSW5pdENhbGxiYWNrcy5zZXQobm9ybWFsaXplZElkZW50aWZpZXIsIGV4aXN0aW5nQ2FsbGJhY2tzKTtcblxuICAgIGNvbnN0IGV4aXN0aW5nSW5zdGFuY2UgPSB0aGlzLmluc3RhbmNlcy5nZXQobm9ybWFsaXplZElkZW50aWZpZXIpO1xuICAgIGlmIChleGlzdGluZ0luc3RhbmNlKSB7XG4gICAgICBjYWxsYmFjayhleGlzdGluZ0luc3RhbmNlLCBub3JtYWxpemVkSWRlbnRpZmllcik7XG4gICAgfVxuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGV4aXN0aW5nQ2FsbGJhY2tzLmRlbGV0ZShjYWxsYmFjayk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2Ugb25Jbml0IGNhbGxiYWNrcyBzeW5jaHJvbm91c2x5XG4gICAqIEBwYXJhbSBpbnN0YW5jZSB0aGUgc2VydmljZSBpbnN0YW5jZWBcbiAgICovXG4gIHByaXZhdGUgaW52b2tlT25Jbml0Q2FsbGJhY2tzKFxuICAgIGluc3RhbmNlOiBOYW1lU2VydmljZU1hcHBpbmdbVF0sXG4gICAgaWRlbnRpZmllcjogc3RyaW5nXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGNhbGxiYWNrcyA9IHRoaXMub25Jbml0Q2FsbGJhY2tzLmdldChpZGVudGlmaWVyKTtcbiAgICBpZiAoIWNhbGxiYWNrcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGNhbGxiYWNrIG9mIGNhbGxiYWNrcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY2FsbGJhY2soaW5zdGFuY2UsIGlkZW50aWZpZXIpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGlnbm9yZSBlcnJvcnMgaW4gdGhlIG9uSW5pdCBjYWxsYmFja1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0T3JJbml0aWFsaXplU2VydmljZSh7XG4gICAgaW5zdGFuY2VJZGVudGlmaWVyLFxuICAgIG9wdGlvbnMgPSB7fVxuICB9OiB7XG4gICAgaW5zdGFuY2VJZGVudGlmaWVyOiBzdHJpbmc7XG4gICAgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9KTogTmFtZVNlcnZpY2VNYXBwaW5nW1RdIHwgbnVsbCB7XG4gICAgbGV0IGluc3RhbmNlID0gdGhpcy5pbnN0YW5jZXMuZ2V0KGluc3RhbmNlSWRlbnRpZmllcik7XG4gICAgaWYgKCFpbnN0YW5jZSAmJiB0aGlzLmNvbXBvbmVudCkge1xuICAgICAgaW5zdGFuY2UgPSB0aGlzLmNvbXBvbmVudC5pbnN0YW5jZUZhY3RvcnkodGhpcy5jb250YWluZXIsIHtcbiAgICAgICAgaW5zdGFuY2VJZGVudGlmaWVyOiBub3JtYWxpemVJZGVudGlmaWVyRm9yRmFjdG9yeShpbnN0YW5jZUlkZW50aWZpZXIpLFxuICAgICAgICBvcHRpb25zXG4gICAgICB9KTtcbiAgICAgIHRoaXMuaW5zdGFuY2VzLnNldChpbnN0YW5jZUlkZW50aWZpZXIsIGluc3RhbmNlISk7XG4gICAgICB0aGlzLmluc3RhbmNlc09wdGlvbnMuc2V0KGluc3RhbmNlSWRlbnRpZmllciwgb3B0aW9ucyk7XG5cbiAgICAgIC8qKlxuICAgICAgICogSW52b2tlIG9uSW5pdCBsaXN0ZW5lcnMuXG4gICAgICAgKiBOb3RlIHRoaXMuY29tcG9uZW50Lm9uSW5zdGFuY2VDcmVhdGVkIGlzIGRpZmZlcmVudCwgd2hpY2ggaXMgdXNlZCBieSB0aGUgY29tcG9uZW50IGNyZWF0b3IsXG4gICAgICAgKiB3aGlsZSBvbkluaXQgbGlzdGVuZXJzIGFyZSByZWdpc3RlcmVkIGJ5IGNvbnN1bWVycyBvZiB0aGUgcHJvdmlkZXIuXG4gICAgICAgKi9cbiAgICAgIHRoaXMuaW52b2tlT25Jbml0Q2FsbGJhY2tzKGluc3RhbmNlISwgaW5zdGFuY2VJZGVudGlmaWVyKTtcblxuICAgICAgLyoqXG4gICAgICAgKiBPcmRlciBpcyBpbXBvcnRhbnRcbiAgICAgICAqIG9uSW5zdGFuY2VDcmVhdGVkKCkgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciB0aGlzLmluc3RhbmNlcy5zZXQoaW5zdGFuY2VJZGVudGlmaWVyLCBpbnN0YW5jZSk7IHdoaWNoXG4gICAgICAgKiBtYWtlcyBgaXNJbml0aWFsaXplZCgpYCByZXR1cm4gdHJ1ZS5cbiAgICAgICAqL1xuICAgICAgaWYgKHRoaXMuY29tcG9uZW50Lm9uSW5zdGFuY2VDcmVhdGVkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGhpcy5jb21wb25lbnQub25JbnN0YW5jZUNyZWF0ZWQoXG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lcixcbiAgICAgICAgICAgIGluc3RhbmNlSWRlbnRpZmllcixcbiAgICAgICAgICAgIGluc3RhbmNlIVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIGlnbm9yZSBlcnJvcnMgaW4gdGhlIG9uSW5zdGFuY2VDcmVhdGVkQ2FsbGJhY2tcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnN0YW5jZSB8fCBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBub3JtYWxpemVJbnN0YW5jZUlkZW50aWZpZXIoXG4gICAgaWRlbnRpZmllcjogc3RyaW5nID0gREVGQVVMVF9FTlRSWV9OQU1FXG4gICk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuY29tcG9uZW50KSB7XG4gICAgICByZXR1cm4gdGhpcy5jb21wb25lbnQubXVsdGlwbGVJbnN0YW5jZXMgPyBpZGVudGlmaWVyIDogREVGQVVMVF9FTlRSWV9OQU1FO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaWRlbnRpZmllcjsgLy8gYXNzdW1lIG11bHRpcGxlIGluc3RhbmNlcyBhcmUgc3VwcG9ydGVkIGJlZm9yZSB0aGUgY29tcG9uZW50IGlzIHByb3ZpZGVkLlxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2hvdWxkQXV0b0luaXRpYWxpemUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgICEhdGhpcy5jb21wb25lbnQgJiZcbiAgICAgIHRoaXMuY29tcG9uZW50Lmluc3RhbnRpYXRpb25Nb2RlICE9PSBJbnN0YW50aWF0aW9uTW9kZS5FWFBMSUNJVFxuICAgICk7XG4gIH1cbn1cblxuLy8gdW5kZWZpbmVkIHNob3VsZCBiZSBwYXNzZWQgdG8gdGhlIHNlcnZpY2UgZmFjdG9yeSBmb3IgdGhlIGRlZmF1bHQgaW5zdGFuY2VcbmZ1bmN0aW9uIG5vcm1hbGl6ZUlkZW50aWZpZXJGb3JGYWN0b3J5KGlkZW50aWZpZXI6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBpZGVudGlmaWVyID09PSBERUZBVUxUX0VOVFJZX05BTUUgPyB1bmRlZmluZWQgOiBpZGVudGlmaWVyO1xufVxuXG5mdW5jdGlvbiBpc0NvbXBvbmVudEVhZ2VyPFQgZXh0ZW5kcyBOYW1lPihjb21wb25lbnQ6IENvbXBvbmVudDxUPik6IGJvb2xlYW4ge1xuICByZXR1cm4gY29tcG9uZW50Lmluc3RhbnRpYXRpb25Nb2RlID09PSBJbnN0YW50aWF0aW9uTW9kZS5FQUdFUjtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXInO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnQnO1xuaW1wb3J0IHsgTmFtZSB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIENvbXBvbmVudENvbnRhaW5lciB0aGF0IHByb3ZpZGVzIFByb3ZpZGVycyBmb3Igc2VydmljZSBuYW1lIFQsIGUuZy4gYGF1dGhgLCBgYXV0aC1pbnRlcm5hbGBcbiAqL1xuZXhwb3J0IGNsYXNzIENvbXBvbmVudENvbnRhaW5lciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvdmlkZXJzID0gbmV3IE1hcDxzdHJpbmcsIFByb3ZpZGVyPE5hbWU+PigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nKSB7fVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gY29tcG9uZW50IENvbXBvbmVudCBiZWluZyBhZGRlZFxuICAgKiBAcGFyYW0gb3ZlcndyaXRlIFdoZW4gYSBjb21wb25lbnQgd2l0aCB0aGUgc2FtZSBuYW1lIGhhcyBhbHJlYWR5IGJlZW4gcmVnaXN0ZXJlZCxcbiAgICogaWYgb3ZlcndyaXRlIGlzIHRydWU6IG92ZXJ3cml0ZSB0aGUgZXhpc3RpbmcgY29tcG9uZW50IHdpdGggdGhlIG5ldyBjb21wb25lbnQgYW5kIGNyZWF0ZSBhIG5ld1xuICAgKiBwcm92aWRlciB3aXRoIHRoZSBuZXcgY29tcG9uZW50LiBJdCBjYW4gYmUgdXNlZnVsIGluIHRlc3RzIHdoZXJlIHlvdSB3YW50IHRvIHVzZSBkaWZmZXJlbnQgbW9ja3NcbiAgICogZm9yIGRpZmZlcmVudCB0ZXN0cy5cbiAgICogaWYgb3ZlcndyaXRlIGlzIGZhbHNlOiB0aHJvdyBhbiBleGNlcHRpb25cbiAgICovXG4gIGFkZENvbXBvbmVudDxUIGV4dGVuZHMgTmFtZT4oY29tcG9uZW50OiBDb21wb25lbnQ8VD4pOiB2b2lkIHtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0UHJvdmlkZXIoY29tcG9uZW50Lm5hbWUpO1xuICAgIGlmIChwcm92aWRlci5pc0NvbXBvbmVudFNldCgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDb21wb25lbnQgJHtjb21wb25lbnQubmFtZX0gaGFzIGFscmVhZHkgYmVlbiByZWdpc3RlcmVkIHdpdGggJHt0aGlzLm5hbWV9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBwcm92aWRlci5zZXRDb21wb25lbnQoY29tcG9uZW50KTtcbiAgfVxuXG4gIGFkZE9yT3ZlcndyaXRlQ29tcG9uZW50PFQgZXh0ZW5kcyBOYW1lPihjb21wb25lbnQ6IENvbXBvbmVudDxUPik6IHZvaWQge1xuICAgIGNvbnN0IHByb3ZpZGVyID0gdGhpcy5nZXRQcm92aWRlcihjb21wb25lbnQubmFtZSk7XG4gICAgaWYgKHByb3ZpZGVyLmlzQ29tcG9uZW50U2V0KCkpIHtcbiAgICAgIC8vIGRlbGV0ZSB0aGUgZXhpc3RpbmcgcHJvdmlkZXIgZnJvbSB0aGUgY29udGFpbmVyLCBzbyB3ZSBjYW4gcmVnaXN0ZXIgdGhlIG5ldyBjb21wb25lbnRcbiAgICAgIHRoaXMucHJvdmlkZXJzLmRlbGV0ZShjb21wb25lbnQubmFtZSk7XG4gICAgfVxuXG4gICAgdGhpcy5hZGRDb21wb25lbnQoY29tcG9uZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXRQcm92aWRlciBwcm92aWRlcyBhIHR5cGUgc2FmZSBpbnRlcmZhY2Ugd2hlcmUgaXQgY2FuIG9ubHkgYmUgY2FsbGVkIHdpdGggYSBmaWVsZCBuYW1lXG4gICAqIHByZXNlbnQgaW4gTmFtZVNlcnZpY2VNYXBwaW5nIGludGVyZmFjZS5cbiAgICpcbiAgICogRmlyZWJhc2UgU0RLcyBwcm92aWRpbmcgc2VydmljZXMgc2hvdWxkIGV4dGVuZCBOYW1lU2VydmljZU1hcHBpbmcgaW50ZXJmYWNlIHRvIHJlZ2lzdGVyXG4gICAqIHRoZW1zZWx2ZXMuXG4gICAqL1xuICBnZXRQcm92aWRlcjxUIGV4dGVuZHMgTmFtZT4obmFtZTogVCk6IFByb3ZpZGVyPFQ+IHtcbiAgICBpZiAodGhpcy5wcm92aWRlcnMuaGFzKG5hbWUpKSB7XG4gICAgICByZXR1cm4gdGhpcy5wcm92aWRlcnMuZ2V0KG5hbWUpIGFzIHVua25vd24gYXMgUHJvdmlkZXI8VD47XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGEgUHJvdmlkZXIgZm9yIGEgc2VydmljZSB0aGF0IGhhc24ndCByZWdpc3RlcmVkIHdpdGggRmlyZWJhc2VcbiAgICBjb25zdCBwcm92aWRlciA9IG5ldyBQcm92aWRlcjxUPihuYW1lLCB0aGlzKTtcbiAgICB0aGlzLnByb3ZpZGVycy5zZXQobmFtZSwgcHJvdmlkZXIgYXMgdW5rbm93biBhcyBQcm92aWRlcjxOYW1lPik7XG5cbiAgICByZXR1cm4gcHJvdmlkZXIgYXMgUHJvdmlkZXI8VD47XG4gIH1cblxuICBnZXRQcm92aWRlcnMoKTogQXJyYXk8UHJvdmlkZXI8TmFtZT4+IHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLnByb3ZpZGVycy52YWx1ZXMoKSk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgdHlwZSBMb2dMZXZlbFN0cmluZyA9XG4gIHwgJ2RlYnVnJ1xuICB8ICd2ZXJib3NlJ1xuICB8ICdpbmZvJ1xuICB8ICd3YXJuJ1xuICB8ICdlcnJvcidcbiAgfCAnc2lsZW50JztcblxuZXhwb3J0IGludGVyZmFjZSBMb2dPcHRpb25zIHtcbiAgbGV2ZWw6IExvZ0xldmVsU3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBMb2dDYWxsYmFjayA9IChjYWxsYmFja1BhcmFtczogTG9nQ2FsbGJhY2tQYXJhbXMpID0+IHZvaWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9nQ2FsbGJhY2tQYXJhbXMge1xuICBsZXZlbDogTG9nTGV2ZWxTdHJpbmc7XG4gIG1lc3NhZ2U6IHN0cmluZztcbiAgYXJnczogdW5rbm93bltdO1xuICB0eXBlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSBjb250YWluZXIgZm9yIGFsbCBvZiB0aGUgTG9nZ2VyIGluc3RhbmNlc1xuICovXG5leHBvcnQgY29uc3QgaW5zdGFuY2VzOiBMb2dnZXJbXSA9IFtdO1xuXG4vKipcbiAqIFRoZSBKUyBTREsgc3VwcG9ydHMgNSBsb2cgbGV2ZWxzIGFuZCBhbHNvIGFsbG93cyBhIHVzZXIgdGhlIGFiaWxpdHkgdG9cbiAqIHNpbGVuY2UgdGhlIGxvZ3MgYWx0b2dldGhlci5cbiAqXG4gKiBUaGUgb3JkZXIgaXMgYSBmb2xsb3dzOlxuICogREVCVUcgPCBWRVJCT1NFIDwgSU5GTyA8IFdBUk4gPCBFUlJPUlxuICpcbiAqIEFsbCBvZiB0aGUgbG9nIHR5cGVzIGFib3ZlIHRoZSBjdXJyZW50IGxvZyBsZXZlbCB3aWxsIGJlIGNhcHR1cmVkIChpLmUuIGlmXG4gKiB5b3Ugc2V0IHRoZSBsb2cgbGV2ZWwgdG8gYElORk9gLCBlcnJvcnMgd2lsbCBzdGlsbCBiZSBsb2dnZWQsIGJ1dCBgREVCVUdgIGFuZFxuICogYFZFUkJPU0VgIGxvZ3Mgd2lsbCBub3QpXG4gKi9cbmV4cG9ydCBlbnVtIExvZ0xldmVsIHtcbiAgREVCVUcsXG4gIFZFUkJPU0UsXG4gIElORk8sXG4gIFdBUk4sXG4gIEVSUk9SLFxuICBTSUxFTlRcbn1cblxuY29uc3QgbGV2ZWxTdHJpbmdUb0VudW06IHsgW2tleSBpbiBMb2dMZXZlbFN0cmluZ106IExvZ0xldmVsIH0gPSB7XG4gICdkZWJ1Zyc6IExvZ0xldmVsLkRFQlVHLFxuICAndmVyYm9zZSc6IExvZ0xldmVsLlZFUkJPU0UsXG4gICdpbmZvJzogTG9nTGV2ZWwuSU5GTyxcbiAgJ3dhcm4nOiBMb2dMZXZlbC5XQVJOLFxuICAnZXJyb3InOiBMb2dMZXZlbC5FUlJPUixcbiAgJ3NpbGVudCc6IExvZ0xldmVsLlNJTEVOVFxufTtcblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBsb2cgbGV2ZWxcbiAqL1xuY29uc3QgZGVmYXVsdExvZ0xldmVsOiBMb2dMZXZlbCA9IExvZ0xldmVsLklORk87XG5cbi8qKlxuICogV2UgYWxsb3cgdXNlcnMgdGhlIGFiaWxpdHkgdG8gcGFzcyB0aGVpciBvd24gbG9nIGhhbmRsZXIuIFdlIHdpbGwgcGFzcyB0aGVcbiAqIHR5cGUgb2YgbG9nLCB0aGUgY3VycmVudCBsb2cgbGV2ZWwsIGFuZCBhbnkgb3RoZXIgYXJndW1lbnRzIHBhc3NlZCAoaS5lLiB0aGVcbiAqIG1lc3NhZ2VzIHRoYXQgdGhlIHVzZXIgd2FudHMgdG8gbG9nKSB0byB0aGlzIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgdHlwZSBMb2dIYW5kbGVyID0gKFxuICBsb2dnZXJJbnN0YW5jZTogTG9nZ2VyLFxuICBsb2dUeXBlOiBMb2dMZXZlbCxcbiAgLi4uYXJnczogdW5rbm93bltdXG4pID0+IHZvaWQ7XG5cbi8qKlxuICogQnkgZGVmYXVsdCwgYGNvbnNvbGUuZGVidWdgIGlzIG5vdCBkaXNwbGF5ZWQgaW4gdGhlIGRldmVsb3BlciBjb25zb2xlIChpblxuICogY2hyb21lKS4gVG8gYXZvaWQgZm9yY2luZyB1c2VycyB0byBoYXZlIHRvIG9wdC1pbiB0byB0aGVzZSBsb2dzIHR3aWNlXG4gKiAoaS5lLiBvbmNlIGZvciBmaXJlYmFzZSwgYW5kIG9uY2UgaW4gdGhlIGNvbnNvbGUpLCB3ZSBhcmUgc2VuZGluZyBgREVCVUdgXG4gKiBsb2dzIHRvIHRoZSBgY29uc29sZS5sb2dgIGZ1bmN0aW9uLlxuICovXG5jb25zdCBDb25zb2xlTWV0aG9kID0ge1xuICBbTG9nTGV2ZWwuREVCVUddOiAnbG9nJyxcbiAgW0xvZ0xldmVsLlZFUkJPU0VdOiAnbG9nJyxcbiAgW0xvZ0xldmVsLklORk9dOiAnaW5mbycsXG4gIFtMb2dMZXZlbC5XQVJOXTogJ3dhcm4nLFxuICBbTG9nTGV2ZWwuRVJST1JdOiAnZXJyb3InXG59O1xuXG4vKipcbiAqIFRoZSBkZWZhdWx0IGxvZyBoYW5kbGVyIHdpbGwgZm9yd2FyZCBERUJVRywgVkVSQk9TRSwgSU5GTywgV0FSTiwgYW5kIEVSUk9SXG4gKiBtZXNzYWdlcyBvbiB0byB0aGVpciBjb3JyZXNwb25kaW5nIGNvbnNvbGUgY291bnRlcnBhcnRzIChpZiB0aGUgbG9nIG1ldGhvZFxuICogaXMgc3VwcG9ydGVkIGJ5IHRoZSBjdXJyZW50IGxvZyBsZXZlbClcbiAqL1xuY29uc3QgZGVmYXVsdExvZ0hhbmRsZXI6IExvZ0hhbmRsZXIgPSAoaW5zdGFuY2UsIGxvZ1R5cGUsIC4uLmFyZ3MpOiB2b2lkID0+IHtcbiAgaWYgKGxvZ1R5cGUgPCBpbnN0YW5jZS5sb2dMZXZlbCkge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gIGNvbnN0IG1ldGhvZCA9IENvbnNvbGVNZXRob2RbbG9nVHlwZSBhcyBrZXlvZiB0eXBlb2YgQ29uc29sZU1ldGhvZF07XG4gIGlmIChtZXRob2QpIHtcbiAgICBjb25zb2xlW21ldGhvZCBhcyAnbG9nJyB8ICdpbmZvJyB8ICd3YXJuJyB8ICdlcnJvciddKFxuICAgICAgYFske25vd31dICAke2luc3RhbmNlLm5hbWV9OmAsXG4gICAgICAuLi5hcmdzXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgQXR0ZW1wdGVkIHRvIGxvZyBhIG1lc3NhZ2Ugd2l0aCBhbiBpbnZhbGlkIGxvZ1R5cGUgKHZhbHVlOiAke2xvZ1R5cGV9KWBcbiAgICApO1xuICB9XG59O1xuXG5leHBvcnQgY2xhc3MgTG9nZ2VyIHtcbiAgLyoqXG4gICAqIEdpdmVzIHlvdSBhbiBpbnN0YW5jZSBvZiBhIExvZ2dlciB0byBjYXB0dXJlIG1lc3NhZ2VzIGFjY29yZGluZyB0b1xuICAgKiBGaXJlYmFzZSdzIGxvZ2dpbmcgc2NoZW1lLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSB0aGF0IHRoZSBsb2dzIHdpbGwgYmUgYXNzb2NpYXRlZCB3aXRoXG4gICAqL1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgbmFtZTogc3RyaW5nKSB7XG4gICAgLyoqXG4gICAgICogQ2FwdHVyZSB0aGUgY3VycmVudCBpbnN0YW5jZSBmb3IgbGF0ZXIgdXNlXG4gICAgICovXG4gICAgaW5zdGFuY2VzLnB1c2godGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGxvZyBsZXZlbCBvZiB0aGUgZ2l2ZW4gTG9nZ2VyIGluc3RhbmNlLlxuICAgKi9cbiAgcHJpdmF0ZSBfbG9nTGV2ZWwgPSBkZWZhdWx0TG9nTGV2ZWw7XG5cbiAgZ2V0IGxvZ0xldmVsKCk6IExvZ0xldmVsIHtcbiAgICByZXR1cm4gdGhpcy5fbG9nTGV2ZWw7XG4gIH1cblxuICBzZXQgbG9nTGV2ZWwodmFsOiBMb2dMZXZlbCkge1xuICAgIGlmICghKHZhbCBpbiBMb2dMZXZlbCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEludmFsaWQgdmFsdWUgXCIke3ZhbH1cIiBhc3NpZ25lZCB0byBcXGBsb2dMZXZlbFxcYGApO1xuICAgIH1cbiAgICB0aGlzLl9sb2dMZXZlbCA9IHZhbDtcbiAgfVxuXG4gIC8vIFdvcmthcm91bmQgZm9yIHNldHRlci9nZXR0ZXIgaGF2aW5nIHRvIGJlIHRoZSBzYW1lIHR5cGUuXG4gIHNldExvZ0xldmVsKHZhbDogTG9nTGV2ZWwgfCBMb2dMZXZlbFN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX2xvZ0xldmVsID0gdHlwZW9mIHZhbCA9PT0gJ3N0cmluZycgPyBsZXZlbFN0cmluZ1RvRW51bVt2YWxdIDogdmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBtYWluIChpbnRlcm5hbCkgbG9nIGhhbmRsZXIgZm9yIHRoZSBMb2dnZXIgaW5zdGFuY2UuXG4gICAqIENhbiBiZSBzZXQgdG8gYSBuZXcgZnVuY3Rpb24gaW4gaW50ZXJuYWwgcGFja2FnZSBjb2RlIGJ1dCBub3QgYnkgdXNlci5cbiAgICovXG4gIHByaXZhdGUgX2xvZ0hhbmRsZXI6IExvZ0hhbmRsZXIgPSBkZWZhdWx0TG9nSGFuZGxlcjtcbiAgZ2V0IGxvZ0hhbmRsZXIoKTogTG9nSGFuZGxlciB7XG4gICAgcmV0dXJuIHRoaXMuX2xvZ0hhbmRsZXI7XG4gIH1cbiAgc2V0IGxvZ0hhbmRsZXIodmFsOiBMb2dIYW5kbGVyKSB7XG4gICAgaWYgKHR5cGVvZiB2YWwgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1ZhbHVlIGFzc2lnbmVkIHRvIGBsb2dIYW5kbGVyYCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICB9XG4gICAgdGhpcy5fbG9nSGFuZGxlciA9IHZhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgb3B0aW9uYWwsIGFkZGl0aW9uYWwsIHVzZXItZGVmaW5lZCBsb2cgaGFuZGxlciBmb3IgdGhlIExvZ2dlciBpbnN0YW5jZS5cbiAgICovXG4gIHByaXZhdGUgX3VzZXJMb2dIYW5kbGVyOiBMb2dIYW5kbGVyIHwgbnVsbCA9IG51bGw7XG4gIGdldCB1c2VyTG9nSGFuZGxlcigpOiBMb2dIYW5kbGVyIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX3VzZXJMb2dIYW5kbGVyO1xuICB9XG4gIHNldCB1c2VyTG9nSGFuZGxlcih2YWw6IExvZ0hhbmRsZXIgfCBudWxsKSB7XG4gICAgdGhpcy5fdXNlckxvZ0hhbmRsZXIgPSB2YWw7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGZ1bmN0aW9ucyBiZWxvdyBhcmUgYWxsIGJhc2VkIG9uIHRoZSBgY29uc29sZWAgaW50ZXJmYWNlXG4gICAqL1xuXG4gIGRlYnVnKC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuICAgIHRoaXMuX3VzZXJMb2dIYW5kbGVyICYmIHRoaXMuX3VzZXJMb2dIYW5kbGVyKHRoaXMsIExvZ0xldmVsLkRFQlVHLCAuLi5hcmdzKTtcbiAgICB0aGlzLl9sb2dIYW5kbGVyKHRoaXMsIExvZ0xldmVsLkRFQlVHLCAuLi5hcmdzKTtcbiAgfVxuICBsb2coLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgdGhpcy5fdXNlckxvZ0hhbmRsZXIgJiZcbiAgICAgIHRoaXMuX3VzZXJMb2dIYW5kbGVyKHRoaXMsIExvZ0xldmVsLlZFUkJPU0UsIC4uLmFyZ3MpO1xuICAgIHRoaXMuX2xvZ0hhbmRsZXIodGhpcywgTG9nTGV2ZWwuVkVSQk9TRSwgLi4uYXJncyk7XG4gIH1cbiAgaW5mbyguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcbiAgICB0aGlzLl91c2VyTG9nSGFuZGxlciAmJiB0aGlzLl91c2VyTG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5JTkZPLCAuLi5hcmdzKTtcbiAgICB0aGlzLl9sb2dIYW5kbGVyKHRoaXMsIExvZ0xldmVsLklORk8sIC4uLmFyZ3MpO1xuICB9XG4gIHdhcm4oLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgdGhpcy5fdXNlckxvZ0hhbmRsZXIgJiYgdGhpcy5fdXNlckxvZ0hhbmRsZXIodGhpcywgTG9nTGV2ZWwuV0FSTiwgLi4uYXJncyk7XG4gICAgdGhpcy5fbG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5XQVJOLCAuLi5hcmdzKTtcbiAgfVxuICBlcnJvciguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcbiAgICB0aGlzLl91c2VyTG9nSGFuZGxlciAmJiB0aGlzLl91c2VyTG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5FUlJPUiwgLi4uYXJncyk7XG4gICAgdGhpcy5fbG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5FUlJPUiwgLi4uYXJncyk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldExvZ0xldmVsKGxldmVsOiBMb2dMZXZlbFN0cmluZyB8IExvZ0xldmVsKTogdm9pZCB7XG4gIGluc3RhbmNlcy5mb3JFYWNoKGluc3QgPT4ge1xuICAgIGluc3Quc2V0TG9nTGV2ZWwobGV2ZWwpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFVzZXJMb2dIYW5kbGVyKFxuICBsb2dDYWxsYmFjazogTG9nQ2FsbGJhY2sgfCBudWxsLFxuICBvcHRpb25zPzogTG9nT3B0aW9uc1xuKTogdm9pZCB7XG4gIGZvciAoY29uc3QgaW5zdGFuY2Ugb2YgaW5zdGFuY2VzKSB7XG4gICAgbGV0IGN1c3RvbUxvZ0xldmVsOiBMb2dMZXZlbCB8IG51bGwgPSBudWxsO1xuICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMubGV2ZWwpIHtcbiAgICAgIGN1c3RvbUxvZ0xldmVsID0gbGV2ZWxTdHJpbmdUb0VudW1bb3B0aW9ucy5sZXZlbF07XG4gICAgfVxuICAgIGlmIChsb2dDYWxsYmFjayA9PT0gbnVsbCkge1xuICAgICAgaW5zdGFuY2UudXNlckxvZ0hhbmRsZXIgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICBpbnN0YW5jZS51c2VyTG9nSGFuZGxlciA9IChcbiAgICAgICAgaW5zdGFuY2U6IExvZ2dlcixcbiAgICAgICAgbGV2ZWw6IExvZ0xldmVsLFxuICAgICAgICAuLi5hcmdzOiB1bmtub3duW11cbiAgICAgICkgPT4ge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gYXJnc1xuICAgICAgICAgIC5tYXAoYXJnID0+IHtcbiAgICAgICAgICAgIGlmIChhcmcgPT0gbnVsbCkge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGFyZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicgfHwgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYXJnIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGFyZy5tZXNzYWdlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXJnKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoaWdub3JlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuZmlsdGVyKGFyZyA9PiBhcmcpXG4gICAgICAgICAgLmpvaW4oJyAnKTtcbiAgICAgICAgaWYgKGxldmVsID49IChjdXN0b21Mb2dMZXZlbCA/PyBpbnN0YW5jZS5sb2dMZXZlbCkpIHtcbiAgICAgICAgICBsb2dDYWxsYmFjayh7XG4gICAgICAgICAgICBsZXZlbDogTG9nTGV2ZWxbbGV2ZWxdLnRvTG93ZXJDYXNlKCkgYXMgTG9nTGV2ZWxTdHJpbmcsXG4gICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgYXJncyxcbiAgICAgICAgICAgIHR5cGU6IGluc3RhbmNlLm5hbWVcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH1cbn1cbiIsICJjb25zdCBpbnN0YW5jZU9mQW55ID0gKG9iamVjdCwgY29uc3RydWN0b3JzKSA9PiBjb25zdHJ1Y3RvcnMuc29tZSgoYykgPT4gb2JqZWN0IGluc3RhbmNlb2YgYyk7XG5cbmxldCBpZGJQcm94eWFibGVUeXBlcztcbmxldCBjdXJzb3JBZHZhbmNlTWV0aG9kcztcbi8vIFRoaXMgaXMgYSBmdW5jdGlvbiB0byBwcmV2ZW50IGl0IHRocm93aW5nIHVwIGluIG5vZGUgZW52aXJvbm1lbnRzLlxuZnVuY3Rpb24gZ2V0SWRiUHJveHlhYmxlVHlwZXMoKSB7XG4gICAgcmV0dXJuIChpZGJQcm94eWFibGVUeXBlcyB8fFxuICAgICAgICAoaWRiUHJveHlhYmxlVHlwZXMgPSBbXG4gICAgICAgICAgICBJREJEYXRhYmFzZSxcbiAgICAgICAgICAgIElEQk9iamVjdFN0b3JlLFxuICAgICAgICAgICAgSURCSW5kZXgsXG4gICAgICAgICAgICBJREJDdXJzb3IsXG4gICAgICAgICAgICBJREJUcmFuc2FjdGlvbixcbiAgICAgICAgXSkpO1xufVxuLy8gVGhpcyBpcyBhIGZ1bmN0aW9uIHRvIHByZXZlbnQgaXQgdGhyb3dpbmcgdXAgaW4gbm9kZSBlbnZpcm9ubWVudHMuXG5mdW5jdGlvbiBnZXRDdXJzb3JBZHZhbmNlTWV0aG9kcygpIHtcbiAgICByZXR1cm4gKGN1cnNvckFkdmFuY2VNZXRob2RzIHx8XG4gICAgICAgIChjdXJzb3JBZHZhbmNlTWV0aG9kcyA9IFtcbiAgICAgICAgICAgIElEQkN1cnNvci5wcm90b3R5cGUuYWR2YW5jZSxcbiAgICAgICAgICAgIElEQkN1cnNvci5wcm90b3R5cGUuY29udGludWUsXG4gICAgICAgICAgICBJREJDdXJzb3IucHJvdG90eXBlLmNvbnRpbnVlUHJpbWFyeUtleSxcbiAgICAgICAgXSkpO1xufVxuY29uc3QgY3Vyc29yUmVxdWVzdE1hcCA9IG5ldyBXZWFrTWFwKCk7XG5jb25zdCB0cmFuc2FjdGlvbkRvbmVNYXAgPSBuZXcgV2Vha01hcCgpO1xuY29uc3QgdHJhbnNhY3Rpb25TdG9yZU5hbWVzTWFwID0gbmV3IFdlYWtNYXAoKTtcbmNvbnN0IHRyYW5zZm9ybUNhY2hlID0gbmV3IFdlYWtNYXAoKTtcbmNvbnN0IHJldmVyc2VUcmFuc2Zvcm1DYWNoZSA9IG5ldyBXZWFrTWFwKCk7XG5mdW5jdGlvbiBwcm9taXNpZnlSZXF1ZXN0KHJlcXVlc3QpIHtcbiAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBjb25zdCB1bmxpc3RlbiA9ICgpID0+IHtcbiAgICAgICAgICAgIHJlcXVlc3QucmVtb3ZlRXZlbnRMaXN0ZW5lcignc3VjY2VzcycsIHN1Y2Nlc3MpO1xuICAgICAgICAgICAgcmVxdWVzdC5yZW1vdmVFdmVudExpc3RlbmVyKCdlcnJvcicsIGVycm9yKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgc3VjY2VzcyA9ICgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUod3JhcChyZXF1ZXN0LnJlc3VsdCkpO1xuICAgICAgICAgICAgdW5saXN0ZW4oKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICByZWplY3QocmVxdWVzdC5lcnJvcik7XG4gICAgICAgICAgICB1bmxpc3RlbigpO1xuICAgICAgICB9O1xuICAgICAgICByZXF1ZXN0LmFkZEV2ZW50TGlzdGVuZXIoJ3N1Y2Nlc3MnLCBzdWNjZXNzKTtcbiAgICAgICAgcmVxdWVzdC5hZGRFdmVudExpc3RlbmVyKCdlcnJvcicsIGVycm9yKTtcbiAgICB9KTtcbiAgICBwcm9taXNlXG4gICAgICAgIC50aGVuKCh2YWx1ZSkgPT4ge1xuICAgICAgICAvLyBTaW5jZSBjdXJzb3JpbmcgcmV1c2VzIHRoZSBJREJSZXF1ZXN0ICgqc2lnaCopLCB3ZSBjYWNoZSBpdCBmb3IgbGF0ZXIgcmV0cmlldmFsXG4gICAgICAgIC8vIChzZWUgd3JhcEZ1bmN0aW9uKS5cbiAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgSURCQ3Vyc29yKSB7XG4gICAgICAgICAgICBjdXJzb3JSZXF1ZXN0TWFwLnNldCh2YWx1ZSwgcmVxdWVzdCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2F0Y2hpbmcgdG8gYXZvaWQgXCJVbmNhdWdodCBQcm9taXNlIGV4Y2VwdGlvbnNcIlxuICAgIH0pXG4gICAgICAgIC5jYXRjaCgoKSA9PiB7IH0pO1xuICAgIC8vIFRoaXMgbWFwcGluZyBleGlzdHMgaW4gcmV2ZXJzZVRyYW5zZm9ybUNhY2hlIGJ1dCBkb2Vzbid0IGRvZXNuJ3QgZXhpc3QgaW4gdHJhbnNmb3JtQ2FjaGUuIFRoaXNcbiAgICAvLyBpcyBiZWNhdXNlIHdlIGNyZWF0ZSBtYW55IHByb21pc2VzIGZyb20gYSBzaW5nbGUgSURCUmVxdWVzdC5cbiAgICByZXZlcnNlVHJhbnNmb3JtQ2FjaGUuc2V0KHByb21pc2UsIHJlcXVlc3QpO1xuICAgIHJldHVybiBwcm9taXNlO1xufVxuZnVuY3Rpb24gY2FjaGVEb25lUHJvbWlzZUZvclRyYW5zYWN0aW9uKHR4KSB7XG4gICAgLy8gRWFybHkgYmFpbCBpZiB3ZSd2ZSBhbHJlYWR5IGNyZWF0ZWQgYSBkb25lIHByb21pc2UgZm9yIHRoaXMgdHJhbnNhY3Rpb24uXG4gICAgaWYgKHRyYW5zYWN0aW9uRG9uZU1hcC5oYXModHgpKVxuICAgICAgICByZXR1cm47XG4gICAgY29uc3QgZG9uZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgdW5saXN0ZW4gPSAoKSA9PiB7XG4gICAgICAgICAgICB0eC5yZW1vdmVFdmVudExpc3RlbmVyKCdjb21wbGV0ZScsIGNvbXBsZXRlKTtcbiAgICAgICAgICAgIHR4LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZXJyb3IpO1xuICAgICAgICAgICAgdHgucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBlcnJvcik7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGNvbXBsZXRlID0gKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgdW5saXN0ZW4oKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgICAgICByZWplY3QodHguZXJyb3IgfHwgbmV3IERPTUV4Y2VwdGlvbignQWJvcnRFcnJvcicsICdBYm9ydEVycm9yJykpO1xuICAgICAgICAgICAgdW5saXN0ZW4oKTtcbiAgICAgICAgfTtcbiAgICAgICAgdHguYWRkRXZlbnRMaXN0ZW5lcignY29tcGxldGUnLCBjb21wbGV0ZSk7XG4gICAgICAgIHR4LmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgZXJyb3IpO1xuICAgICAgICB0eC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIGVycm9yKTtcbiAgICB9KTtcbiAgICAvLyBDYWNoZSBpdCBmb3IgbGF0ZXIgcmV0cmlldmFsLlxuICAgIHRyYW5zYWN0aW9uRG9uZU1hcC5zZXQodHgsIGRvbmUpO1xufVxubGV0IGlkYlByb3h5VHJhcHMgPSB7XG4gICAgZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpIHtcbiAgICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIElEQlRyYW5zYWN0aW9uKSB7XG4gICAgICAgICAgICAvLyBTcGVjaWFsIGhhbmRsaW5nIGZvciB0cmFuc2FjdGlvbi5kb25lLlxuICAgICAgICAgICAgaWYgKHByb3AgPT09ICdkb25lJylcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb25Eb25lTWFwLmdldCh0YXJnZXQpO1xuICAgICAgICAgICAgLy8gUG9seWZpbGwgZm9yIG9iamVjdFN0b3JlTmFtZXMgYmVjYXVzZSBvZiBFZGdlLlxuICAgICAgICAgICAgaWYgKHByb3AgPT09ICdvYmplY3RTdG9yZU5hbWVzJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0YXJnZXQub2JqZWN0U3RvcmVOYW1lcyB8fCB0cmFuc2FjdGlvblN0b3JlTmFtZXNNYXAuZ2V0KHRhcmdldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNYWtlIHR4LnN0b3JlIHJldHVybiB0aGUgb25seSBzdG9yZSBpbiB0aGUgdHJhbnNhY3Rpb24sIG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBhcmUgbWFueS5cbiAgICAgICAgICAgIGlmIChwcm9wID09PSAnc3RvcmUnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlY2VpdmVyLm9iamVjdFN0b3JlTmFtZXNbMV1cbiAgICAgICAgICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgOiByZWNlaXZlci5vYmplY3RTdG9yZShyZWNlaXZlci5vYmplY3RTdG9yZU5hbWVzWzBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBFbHNlIHRyYW5zZm9ybSB3aGF0ZXZlciB3ZSBnZXQgYmFjay5cbiAgICAgICAgcmV0dXJuIHdyYXAodGFyZ2V0W3Byb3BdKTtcbiAgICB9LFxuICAgIHNldCh0YXJnZXQsIHByb3AsIHZhbHVlKSB7XG4gICAgICAgIHRhcmdldFtwcm9wXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LFxuICAgIGhhcyh0YXJnZXQsIHByb3ApIHtcbiAgICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIElEQlRyYW5zYWN0aW9uICYmXG4gICAgICAgICAgICAocHJvcCA9PT0gJ2RvbmUnIHx8IHByb3AgPT09ICdzdG9yZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvcCBpbiB0YXJnZXQ7XG4gICAgfSxcbn07XG5mdW5jdGlvbiByZXBsYWNlVHJhcHMoY2FsbGJhY2spIHtcbiAgICBpZGJQcm94eVRyYXBzID0gY2FsbGJhY2soaWRiUHJveHlUcmFwcyk7XG59XG5mdW5jdGlvbiB3cmFwRnVuY3Rpb24oZnVuYykge1xuICAgIC8vIER1ZSB0byBleHBlY3RlZCBvYmplY3QgZXF1YWxpdHkgKHdoaWNoIGlzIGVuZm9yY2VkIGJ5IHRoZSBjYWNoaW5nIGluIGB3cmFwYCksIHdlXG4gICAgLy8gb25seSBjcmVhdGUgb25lIG5ldyBmdW5jIHBlciBmdW5jLlxuICAgIC8vIEVkZ2UgZG9lc24ndCBzdXBwb3J0IG9iamVjdFN0b3JlTmFtZXMgKGJvb28pLCBzbyB3ZSBwb2x5ZmlsbCBpdCBoZXJlLlxuICAgIGlmIChmdW5jID09PSBJREJEYXRhYmFzZS5wcm90b3R5cGUudHJhbnNhY3Rpb24gJiZcbiAgICAgICAgISgnb2JqZWN0U3RvcmVOYW1lcycgaW4gSURCVHJhbnNhY3Rpb24ucHJvdG90eXBlKSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHN0b3JlTmFtZXMsIC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIGNvbnN0IHR4ID0gZnVuYy5jYWxsKHVud3JhcCh0aGlzKSwgc3RvcmVOYW1lcywgLi4uYXJncyk7XG4gICAgICAgICAgICB0cmFuc2FjdGlvblN0b3JlTmFtZXNNYXAuc2V0KHR4LCBzdG9yZU5hbWVzLnNvcnQgPyBzdG9yZU5hbWVzLnNvcnQoKSA6IFtzdG9yZU5hbWVzXSk7XG4gICAgICAgICAgICByZXR1cm4gd3JhcCh0eCk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIC8vIEN1cnNvciBtZXRob2RzIGFyZSBzcGVjaWFsLCBhcyB0aGUgYmVoYXZpb3VyIGlzIGEgbGl0dGxlIG1vcmUgZGlmZmVyZW50IHRvIHN0YW5kYXJkIElEQi4gSW5cbiAgICAvLyBJREIsIHlvdSBhZHZhbmNlIHRoZSBjdXJzb3IgYW5kIHdhaXQgZm9yIGEgbmV3ICdzdWNjZXNzJyBvbiB0aGUgSURCUmVxdWVzdCB0aGF0IGdhdmUgeW91IHRoZVxuICAgIC8vIGN1cnNvci4gSXQncyBraW5kYSBsaWtlIGEgcHJvbWlzZSB0aGF0IGNhbiByZXNvbHZlIHdpdGggbWFueSB2YWx1ZXMuIFRoYXQgZG9lc24ndCBtYWtlIHNlbnNlXG4gICAgLy8gd2l0aCByZWFsIHByb21pc2VzLCBzbyBlYWNoIGFkdmFuY2UgbWV0aG9kcyByZXR1cm5zIGEgbmV3IHByb21pc2UgZm9yIHRoZSBjdXJzb3Igb2JqZWN0LCBvclxuICAgIC8vIHVuZGVmaW5lZCBpZiB0aGUgZW5kIG9mIHRoZSBjdXJzb3IgaGFzIGJlZW4gcmVhY2hlZC5cbiAgICBpZiAoZ2V0Q3Vyc29yQWR2YW5jZU1ldGhvZHMoKS5pbmNsdWRlcyhmdW5jKSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgICAgIC8vIENhbGxpbmcgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uIHdpdGggdGhlIHByb3h5IGFzICd0aGlzJyBjYXVzZXMgSUxMRUdBTCBJTlZPQ0FUSU9OLCBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBvcmlnaW5hbCBvYmplY3QuXG4gICAgICAgICAgICBmdW5jLmFwcGx5KHVud3JhcCh0aGlzKSwgYXJncyk7XG4gICAgICAgICAgICByZXR1cm4gd3JhcChjdXJzb3JSZXF1ZXN0TWFwLmdldCh0aGlzKSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICAvLyBDYWxsaW5nIHRoZSBvcmlnaW5hbCBmdW5jdGlvbiB3aXRoIHRoZSBwcm94eSBhcyAndGhpcycgY2F1c2VzIElMTEVHQUwgSU5WT0NBVElPTiwgc28gd2UgdXNlXG4gICAgICAgIC8vIHRoZSBvcmlnaW5hbCBvYmplY3QuXG4gICAgICAgIHJldHVybiB3cmFwKGZ1bmMuYXBwbHkodW53cmFwKHRoaXMpLCBhcmdzKSk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHRyYW5zZm9ybUNhY2hhYmxlVmFsdWUodmFsdWUpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKVxuICAgICAgICByZXR1cm4gd3JhcEZ1bmN0aW9uKHZhbHVlKTtcbiAgICAvLyBUaGlzIGRvZXNuJ3QgcmV0dXJuLCBpdCBqdXN0IGNyZWF0ZXMgYSAnZG9uZScgcHJvbWlzZSBmb3IgdGhlIHRyYW5zYWN0aW9uLFxuICAgIC8vIHdoaWNoIGlzIGxhdGVyIHJldHVybmVkIGZvciB0cmFuc2FjdGlvbi5kb25lIChzZWUgaWRiT2JqZWN0SGFuZGxlcikuXG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgSURCVHJhbnNhY3Rpb24pXG4gICAgICAgIGNhY2hlRG9uZVByb21pc2VGb3JUcmFuc2FjdGlvbih2YWx1ZSk7XG4gICAgaWYgKGluc3RhbmNlT2ZBbnkodmFsdWUsIGdldElkYlByb3h5YWJsZVR5cGVzKCkpKVxuICAgICAgICByZXR1cm4gbmV3IFByb3h5KHZhbHVlLCBpZGJQcm94eVRyYXBzKTtcbiAgICAvLyBSZXR1cm4gdGhlIHNhbWUgdmFsdWUgYmFjayBpZiB3ZSdyZSBub3QgZ29pbmcgdG8gdHJhbnNmb3JtIGl0LlxuICAgIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIHdyYXAodmFsdWUpIHtcbiAgICAvLyBXZSBzb21ldGltZXMgZ2VuZXJhdGUgbXVsdGlwbGUgcHJvbWlzZXMgZnJvbSBhIHNpbmdsZSBJREJSZXF1ZXN0IChlZyB3aGVuIGN1cnNvcmluZyksIGJlY2F1c2VcbiAgICAvLyBJREIgaXMgd2VpcmQgYW5kIGEgc2luZ2xlIElEQlJlcXVlc3QgY2FuIHlpZWxkIG1hbnkgcmVzcG9uc2VzLCBzbyB0aGVzZSBjYW4ndCBiZSBjYWNoZWQuXG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgSURCUmVxdWVzdClcbiAgICAgICAgcmV0dXJuIHByb21pc2lmeVJlcXVlc3QodmFsdWUpO1xuICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgdHJhbnNmb3JtZWQgdGhpcyB2YWx1ZSBiZWZvcmUsIHJldXNlIHRoZSB0cmFuc2Zvcm1lZCB2YWx1ZS5cbiAgICAvLyBUaGlzIGlzIGZhc3RlciwgYnV0IGl0IGFsc28gcHJvdmlkZXMgb2JqZWN0IGVxdWFsaXR5LlxuICAgIGlmICh0cmFuc2Zvcm1DYWNoZS5oYXModmFsdWUpKVxuICAgICAgICByZXR1cm4gdHJhbnNmb3JtQ2FjaGUuZ2V0KHZhbHVlKTtcbiAgICBjb25zdCBuZXdWYWx1ZSA9IHRyYW5zZm9ybUNhY2hhYmxlVmFsdWUodmFsdWUpO1xuICAgIC8vIE5vdCBhbGwgdHlwZXMgYXJlIHRyYW5zZm9ybWVkLlxuICAgIC8vIFRoZXNlIG1heSBiZSBwcmltaXRpdmUgdHlwZXMsIHNvIHRoZXkgY2FuJ3QgYmUgV2Vha01hcCBrZXlzLlxuICAgIGlmIChuZXdWYWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgdHJhbnNmb3JtQ2FjaGUuc2V0KHZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgIHJldmVyc2VUcmFuc2Zvcm1DYWNoZS5zZXQobmV3VmFsdWUsIHZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld1ZhbHVlO1xufVxuY29uc3QgdW53cmFwID0gKHZhbHVlKSA9PiByZXZlcnNlVHJhbnNmb3JtQ2FjaGUuZ2V0KHZhbHVlKTtcblxuZXhwb3J0IHsgcmV2ZXJzZVRyYW5zZm9ybUNhY2hlIGFzIGEsIGluc3RhbmNlT2ZBbnkgYXMgaSwgcmVwbGFjZVRyYXBzIGFzIHIsIHVud3JhcCBhcyB1LCB3cmFwIGFzIHcgfTtcbiIsICJpbXBvcnQgeyB3IGFzIHdyYXAsIHIgYXMgcmVwbGFjZVRyYXBzIH0gZnJvbSAnLi93cmFwLWlkYi12YWx1ZS5qcyc7XG5leHBvcnQgeyB1IGFzIHVud3JhcCwgdyBhcyB3cmFwIH0gZnJvbSAnLi93cmFwLWlkYi12YWx1ZS5qcyc7XG5cbi8qKlxuICogT3BlbiBhIGRhdGFiYXNlLlxuICpcbiAqIEBwYXJhbSBuYW1lIE5hbWUgb2YgdGhlIGRhdGFiYXNlLlxuICogQHBhcmFtIHZlcnNpb24gU2NoZW1hIHZlcnNpb24uXG4gKiBAcGFyYW0gY2FsbGJhY2tzIEFkZGl0aW9uYWwgY2FsbGJhY2tzLlxuICovXG5mdW5jdGlvbiBvcGVuREIobmFtZSwgdmVyc2lvbiwgeyBibG9ja2VkLCB1cGdyYWRlLCBibG9ja2luZywgdGVybWluYXRlZCB9ID0ge30pIHtcbiAgICBjb25zdCByZXF1ZXN0ID0gaW5kZXhlZERCLm9wZW4obmFtZSwgdmVyc2lvbik7XG4gICAgY29uc3Qgb3BlblByb21pc2UgPSB3cmFwKHJlcXVlc3QpO1xuICAgIGlmICh1cGdyYWRlKSB7XG4gICAgICAgIHJlcXVlc3QuYWRkRXZlbnRMaXN0ZW5lcigndXBncmFkZW5lZWRlZCcsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgdXBncmFkZSh3cmFwKHJlcXVlc3QucmVzdWx0KSwgZXZlbnQub2xkVmVyc2lvbiwgZXZlbnQubmV3VmVyc2lvbiwgd3JhcChyZXF1ZXN0LnRyYW5zYWN0aW9uKSwgZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGJsb2NrZWQpIHtcbiAgICAgICAgcmVxdWVzdC5hZGRFdmVudExpc3RlbmVyKCdibG9ja2VkJywgKGV2ZW50KSA9PiBibG9ja2VkKFxuICAgICAgICAvLyBDYXN0aW5nIGR1ZSB0byBodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L1R5cGVTY3JpcHQtRE9NLWxpYi1nZW5lcmF0b3IvcHVsbC8xNDA1XG4gICAgICAgIGV2ZW50Lm9sZFZlcnNpb24sIGV2ZW50Lm5ld1ZlcnNpb24sIGV2ZW50KSk7XG4gICAgfVxuICAgIG9wZW5Qcm9taXNlXG4gICAgICAgIC50aGVuKChkYikgPT4ge1xuICAgICAgICBpZiAodGVybWluYXRlZClcbiAgICAgICAgICAgIGRiLmFkZEV2ZW50TGlzdGVuZXIoJ2Nsb3NlJywgKCkgPT4gdGVybWluYXRlZCgpKTtcbiAgICAgICAgaWYgKGJsb2NraW5nKSB7XG4gICAgICAgICAgICBkYi5hZGRFdmVudExpc3RlbmVyKCd2ZXJzaW9uY2hhbmdlJywgKGV2ZW50KSA9PiBibG9ja2luZyhldmVudC5vbGRWZXJzaW9uLCBldmVudC5uZXdWZXJzaW9uLCBldmVudCkpO1xuICAgICAgICB9XG4gICAgfSlcbiAgICAgICAgLmNhdGNoKCgpID0+IHsgfSk7XG4gICAgcmV0dXJuIG9wZW5Qcm9taXNlO1xufVxuLyoqXG4gKiBEZWxldGUgYSBkYXRhYmFzZS5cbiAqXG4gKiBAcGFyYW0gbmFtZSBOYW1lIG9mIHRoZSBkYXRhYmFzZS5cbiAqL1xuZnVuY3Rpb24gZGVsZXRlREIobmFtZSwgeyBibG9ja2VkIH0gPSB7fSkge1xuICAgIGNvbnN0IHJlcXVlc3QgPSBpbmRleGVkREIuZGVsZXRlRGF0YWJhc2UobmFtZSk7XG4gICAgaWYgKGJsb2NrZWQpIHtcbiAgICAgICAgcmVxdWVzdC5hZGRFdmVudExpc3RlbmVyKCdibG9ja2VkJywgKGV2ZW50KSA9PiBibG9ja2VkKFxuICAgICAgICAvLyBDYXN0aW5nIGR1ZSB0byBodHRwczovL2dpdGh1Yi5jb20vbWljcm9zb2Z0L1R5cGVTY3JpcHQtRE9NLWxpYi1nZW5lcmF0b3IvcHVsbC8xNDA1XG4gICAgICAgIGV2ZW50Lm9sZFZlcnNpb24sIGV2ZW50KSk7XG4gICAgfVxuICAgIHJldHVybiB3cmFwKHJlcXVlc3QpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbn1cblxuY29uc3QgcmVhZE1ldGhvZHMgPSBbJ2dldCcsICdnZXRLZXknLCAnZ2V0QWxsJywgJ2dldEFsbEtleXMnLCAnY291bnQnXTtcbmNvbnN0IHdyaXRlTWV0aG9kcyA9IFsncHV0JywgJ2FkZCcsICdkZWxldGUnLCAnY2xlYXInXTtcbmNvbnN0IGNhY2hlZE1ldGhvZHMgPSBuZXcgTWFwKCk7XG5mdW5jdGlvbiBnZXRNZXRob2QodGFyZ2V0LCBwcm9wKSB7XG4gICAgaWYgKCEodGFyZ2V0IGluc3RhbmNlb2YgSURCRGF0YWJhc2UgJiZcbiAgICAgICAgIShwcm9wIGluIHRhcmdldCkgJiZcbiAgICAgICAgdHlwZW9mIHByb3AgPT09ICdzdHJpbmcnKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChjYWNoZWRNZXRob2RzLmdldChwcm9wKSlcbiAgICAgICAgcmV0dXJuIGNhY2hlZE1ldGhvZHMuZ2V0KHByb3ApO1xuICAgIGNvbnN0IHRhcmdldEZ1bmNOYW1lID0gcHJvcC5yZXBsYWNlKC9Gcm9tSW5kZXgkLywgJycpO1xuICAgIGNvbnN0IHVzZUluZGV4ID0gcHJvcCAhPT0gdGFyZ2V0RnVuY05hbWU7XG4gICAgY29uc3QgaXNXcml0ZSA9IHdyaXRlTWV0aG9kcy5pbmNsdWRlcyh0YXJnZXRGdW5jTmFtZSk7XG4gICAgaWYgKFxuICAgIC8vIEJhaWwgaWYgdGhlIHRhcmdldCBkb2Vzbid0IGV4aXN0IG9uIHRoZSB0YXJnZXQuIEVnLCBnZXRBbGwgaXNuJ3QgaW4gRWRnZS5cbiAgICAhKHRhcmdldEZ1bmNOYW1lIGluICh1c2VJbmRleCA/IElEQkluZGV4IDogSURCT2JqZWN0U3RvcmUpLnByb3RvdHlwZSkgfHxcbiAgICAgICAgIShpc1dyaXRlIHx8IHJlYWRNZXRob2RzLmluY2x1ZGVzKHRhcmdldEZ1bmNOYW1lKSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBtZXRob2QgPSBhc3luYyBmdW5jdGlvbiAoc3RvcmVOYW1lLCAuLi5hcmdzKSB7XG4gICAgICAgIC8vIGlzV3JpdGUgPyAncmVhZHdyaXRlJyA6IHVuZGVmaW5lZCBnemlwcHMgYmV0dGVyLCBidXQgZmFpbHMgaW4gRWRnZSA6KFxuICAgICAgICBjb25zdCB0eCA9IHRoaXMudHJhbnNhY3Rpb24oc3RvcmVOYW1lLCBpc1dyaXRlID8gJ3JlYWR3cml0ZScgOiAncmVhZG9ubHknKTtcbiAgICAgICAgbGV0IHRhcmdldCA9IHR4LnN0b3JlO1xuICAgICAgICBpZiAodXNlSW5kZXgpXG4gICAgICAgICAgICB0YXJnZXQgPSB0YXJnZXQuaW5kZXgoYXJncy5zaGlmdCgpKTtcbiAgICAgICAgLy8gTXVzdCByZWplY3QgaWYgb3AgcmVqZWN0cy5cbiAgICAgICAgLy8gSWYgaXQncyBhIHdyaXRlIG9wZXJhdGlvbiwgbXVzdCByZWplY3QgaWYgdHguZG9uZSByZWplY3RzLlxuICAgICAgICAvLyBNdXN0IHJlamVjdCB3aXRoIG9wIHJlamVjdGlvbiBmaXJzdC5cbiAgICAgICAgLy8gTXVzdCByZXNvbHZlIHdpdGggb3AgdmFsdWUuXG4gICAgICAgIC8vIE11c3QgaGFuZGxlIGJvdGggcHJvbWlzZXMgKG5vIHVuaGFuZGxlZCByZWplY3Rpb25zKVxuICAgICAgICByZXR1cm4gKGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIHRhcmdldFt0YXJnZXRGdW5jTmFtZV0oLi4uYXJncyksXG4gICAgICAgICAgICBpc1dyaXRlICYmIHR4LmRvbmUsXG4gICAgICAgIF0pKVswXTtcbiAgICB9O1xuICAgIGNhY2hlZE1ldGhvZHMuc2V0KHByb3AsIG1ldGhvZCk7XG4gICAgcmV0dXJuIG1ldGhvZDtcbn1cbnJlcGxhY2VUcmFwcygob2xkVHJhcHMpID0+ICh7XG4gICAgLi4ub2xkVHJhcHMsXG4gICAgZ2V0OiAodGFyZ2V0LCBwcm9wLCByZWNlaXZlcikgPT4gZ2V0TWV0aG9kKHRhcmdldCwgcHJvcCkgfHwgb2xkVHJhcHMuZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpLFxuICAgIGhhczogKHRhcmdldCwgcHJvcCkgPT4gISFnZXRNZXRob2QodGFyZ2V0LCBwcm9wKSB8fCBvbGRUcmFwcy5oYXModGFyZ2V0LCBwcm9wKSxcbn0pKTtcblxuZXhwb3J0IHsgZGVsZXRlREIsIG9wZW5EQiB9O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIENvbXBvbmVudENvbnRhaW5lcixcbiAgQ29tcG9uZW50VHlwZSxcbiAgUHJvdmlkZXIsXG4gIE5hbWVcbn0gZnJvbSAnQGZpcmViYXNlL2NvbXBvbmVudCc7XG5pbXBvcnQgeyBQbGF0Zm9ybUxvZ2dlclNlcnZpY2UsIFZlcnNpb25TZXJ2aWNlIH0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBjbGFzcyBQbGF0Zm9ybUxvZ2dlclNlcnZpY2VJbXBsIGltcGxlbWVudHMgUGxhdGZvcm1Mb2dnZXJTZXJ2aWNlIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBjb250YWluZXI6IENvbXBvbmVudENvbnRhaW5lcikge31cbiAgLy8gSW4gaW5pdGlhbCBpbXBsZW1lbnRhdGlvbiwgdGhpcyB3aWxsIGJlIGNhbGxlZCBieSBpbnN0YWxsYXRpb25zIG9uXG4gIC8vIGF1dGggdG9rZW4gcmVmcmVzaCwgYW5kIGluc3RhbGxhdGlvbnMgd2lsbCBzZW5kIHRoaXMgc3RyaW5nLlxuICBnZXRQbGF0Zm9ybUluZm9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcm92aWRlcnMgPSB0aGlzLmNvbnRhaW5lci5nZXRQcm92aWRlcnMoKTtcbiAgICAvLyBMb29wIHRocm91Z2ggcHJvdmlkZXJzIGFuZCBnZXQgbGlicmFyeS92ZXJzaW9uIHBhaXJzIGZyb20gYW55IHRoYXQgYXJlXG4gICAgLy8gdmVyc2lvbiBjb21wb25lbnRzLlxuICAgIHJldHVybiBwcm92aWRlcnNcbiAgICAgIC5tYXAocHJvdmlkZXIgPT4ge1xuICAgICAgICBpZiAoaXNWZXJzaW9uU2VydmljZVByb3ZpZGVyKHByb3ZpZGVyKSkge1xuICAgICAgICAgIGNvbnN0IHNlcnZpY2UgPSBwcm92aWRlci5nZXRJbW1lZGlhdGUoKSBhcyBWZXJzaW9uU2VydmljZTtcbiAgICAgICAgICByZXR1cm4gYCR7c2VydmljZS5saWJyYXJ5fS8ke3NlcnZpY2UudmVyc2lvbn1gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmZpbHRlcihsb2dTdHJpbmcgPT4gbG9nU3RyaW5nKVxuICAgICAgLmpvaW4oJyAnKTtcbiAgfVxufVxuLyoqXG4gKlxuICogQHBhcmFtIHByb3ZpZGVyIGNoZWNrIGlmIHRoaXMgcHJvdmlkZXIgcHJvdmlkZXMgYSBWZXJzaW9uU2VydmljZVxuICpcbiAqIE5PVEU6IFVzaW5nIFByb3ZpZGVyPCdhcHAtdmVyc2lvbic+IGlzIGEgaGFjayB0byBpbmRpY2F0ZSB0aGF0IHRoZSBwcm92aWRlclxuICogcHJvdmlkZXMgVmVyc2lvblNlcnZpY2UuIFRoZSBwcm92aWRlciBpcyBub3QgbmVjZXNzYXJpbHkgYSAnYXBwLXZlcnNpb24nXG4gKiBwcm92aWRlci5cbiAqL1xuZnVuY3Rpb24gaXNWZXJzaW9uU2VydmljZVByb3ZpZGVyKHByb3ZpZGVyOiBQcm92aWRlcjxOYW1lPik6IGJvb2xlYW4ge1xuICBjb25zdCBjb21wb25lbnQgPSBwcm92aWRlci5nZXRDb21wb25lbnQoKTtcbiAgcmV0dXJuIGNvbXBvbmVudD8udHlwZSA9PT0gQ29tcG9uZW50VHlwZS5WRVJTSU9OO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJ0BmaXJlYmFzZS9sb2dnZXInO1xuXG5leHBvcnQgY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcignQGZpcmViYXNlL2FwcCcpO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IG5hbWUgYXMgYXBwTmFtZSB9IGZyb20gJy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGFwcENvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi9hcHAtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGFuYWx5dGljc0NvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9hbmFseXRpY3MtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGFuYWx5dGljc05hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9hbmFseXRpY3MvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYXBwQ2hlY2tDb21wYXROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvYXBwLWNoZWNrLWNvbXBhdC9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBhcHBDaGVja05hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9hcHAtY2hlY2svcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYXV0aE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9hdXRoL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGF1dGhDb21wYXROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvYXV0aC1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgZGF0YWJhc2VOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvZGF0YWJhc2UvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgZGF0YWNvbm5lY3ROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvZGF0YS1jb25uZWN0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGRhdGFiYXNlQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2RhdGFiYXNlLWNvbXBhdC9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBmdW5jdGlvbnNOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvZnVuY3Rpb25zL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGZ1bmN0aW9uc0NvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9mdW5jdGlvbnMtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGluc3RhbGxhdGlvbnNOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvaW5zdGFsbGF0aW9ucy9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBpbnN0YWxsYXRpb25zQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2luc3RhbGxhdGlvbnMtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIG1lc3NhZ2luZ05hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9tZXNzYWdpbmcvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgbWVzc2FnaW5nQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL21lc3NhZ2luZy1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgcGVyZm9ybWFuY2VOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvcGVyZm9ybWFuY2UvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgcGVyZm9ybWFuY2VDb21wYXROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvcGVyZm9ybWFuY2UtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIHJlbW90ZUNvbmZpZ05hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9yZW1vdGUtY29uZmlnL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIHJlbW90ZUNvbmZpZ0NvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9yZW1vdGUtY29uZmlnLWNvbXBhdC9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBzdG9yYWdlTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL3N0b3JhZ2UvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgc3RvcmFnZUNvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9zdG9yYWdlLWNvbXBhdC9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBmaXJlc3RvcmVOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvZmlyZXN0b3JlL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGFpTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2FpL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGZpcmVzdG9yZUNvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9maXJlc3RvcmUtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIHBhY2thZ2VOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvZmlyZWJhc2UvcGFja2FnZS5qc29uJztcblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBhcHAgbmFtZVxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9FTlRSWV9OQU1FID0gJ1tERUZBVUxUXSc7XG5cbmV4cG9ydCBjb25zdCBQTEFURk9STV9MT0dfU1RSSU5HID0ge1xuICBbYXBwTmFtZV06ICdmaXJlLWNvcmUnLFxuICBbYXBwQ29tcGF0TmFtZV06ICdmaXJlLWNvcmUtY29tcGF0JyxcbiAgW2FuYWx5dGljc05hbWVdOiAnZmlyZS1hbmFseXRpY3MnLFxuICBbYW5hbHl0aWNzQ29tcGF0TmFtZV06ICdmaXJlLWFuYWx5dGljcy1jb21wYXQnLFxuICBbYXBwQ2hlY2tOYW1lXTogJ2ZpcmUtYXBwLWNoZWNrJyxcbiAgW2FwcENoZWNrQ29tcGF0TmFtZV06ICdmaXJlLWFwcC1jaGVjay1jb21wYXQnLFxuICBbYXV0aE5hbWVdOiAnZmlyZS1hdXRoJyxcbiAgW2F1dGhDb21wYXROYW1lXTogJ2ZpcmUtYXV0aC1jb21wYXQnLFxuICBbZGF0YWJhc2VOYW1lXTogJ2ZpcmUtcnRkYicsXG4gIFtkYXRhY29ubmVjdE5hbWVdOiAnZmlyZS1kYXRhLWNvbm5lY3QnLFxuICBbZGF0YWJhc2VDb21wYXROYW1lXTogJ2ZpcmUtcnRkYi1jb21wYXQnLFxuICBbZnVuY3Rpb25zTmFtZV06ICdmaXJlLWZuJyxcbiAgW2Z1bmN0aW9uc0NvbXBhdE5hbWVdOiAnZmlyZS1mbi1jb21wYXQnLFxuICBbaW5zdGFsbGF0aW9uc05hbWVdOiAnZmlyZS1paWQnLFxuICBbaW5zdGFsbGF0aW9uc0NvbXBhdE5hbWVdOiAnZmlyZS1paWQtY29tcGF0JyxcbiAgW21lc3NhZ2luZ05hbWVdOiAnZmlyZS1mY20nLFxuICBbbWVzc2FnaW5nQ29tcGF0TmFtZV06ICdmaXJlLWZjbS1jb21wYXQnLFxuICBbcGVyZm9ybWFuY2VOYW1lXTogJ2ZpcmUtcGVyZicsXG4gIFtwZXJmb3JtYW5jZUNvbXBhdE5hbWVdOiAnZmlyZS1wZXJmLWNvbXBhdCcsXG4gIFtyZW1vdGVDb25maWdOYW1lXTogJ2ZpcmUtcmMnLFxuICBbcmVtb3RlQ29uZmlnQ29tcGF0TmFtZV06ICdmaXJlLXJjLWNvbXBhdCcsXG4gIFtzdG9yYWdlTmFtZV06ICdmaXJlLWdjcycsXG4gIFtzdG9yYWdlQ29tcGF0TmFtZV06ICdmaXJlLWdjcy1jb21wYXQnLFxuICBbZmlyZXN0b3JlTmFtZV06ICdmaXJlLWZzdCcsXG4gIFtmaXJlc3RvcmVDb21wYXROYW1lXTogJ2ZpcmUtZnN0LWNvbXBhdCcsXG4gIFthaU5hbWVdOiAnZmlyZS12ZXJ0ZXgnLFxuICAnZmlyZS1qcyc6ICdmaXJlLWpzJywgLy8gUGxhdGZvcm0gaWRlbnRpZmllciBmb3IgSlMgU0RLLlxuICBbcGFja2FnZU5hbWVdOiAnZmlyZS1qcy1hbGwnXG59IGFzIGNvbnN0O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEZpcmViYXNlQXBwLFxuICBGaXJlYmFzZUFwcFNldHRpbmdzLFxuICBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzLFxuICBGaXJlYmFzZU9wdGlvbnMsXG4gIEZpcmViYXNlU2VydmVyQXBwXG59IGZyb20gJy4vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IENvbXBvbmVudCwgUHJvdmlkZXIsIE5hbWUgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCB7IERFRkFVTFRfRU5UUllfTkFNRSB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IEZpcmViYXNlQXBwSW1wbCB9IGZyb20gJy4vZmlyZWJhc2VBcHAnO1xuaW1wb3J0IHsgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsIH0gZnJvbSAnLi9maXJlYmFzZVNlcnZlckFwcCc7XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBfYXBwcyA9IG5ldyBNYXA8c3RyaW5nLCBGaXJlYmFzZUFwcD4oKTtcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IF9zZXJ2ZXJBcHBzID0gbmV3IE1hcDxzdHJpbmcsIEZpcmViYXNlU2VydmVyQXBwPigpO1xuXG4vKipcbiAqIFJlZ2lzdGVyZWQgY29tcG9uZW50cy5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmV4cG9ydCBjb25zdCBfY29tcG9uZW50cyA9IG5ldyBNYXA8c3RyaW5nLCBDb21wb25lbnQ8YW55Pj4oKTtcblxuLyoqXG4gKiBAcGFyYW0gY29tcG9uZW50IC0gdGhlIGNvbXBvbmVudCBiZWluZyBhZGRlZCB0byB0aGlzIGFwcCdzIGNvbnRhaW5lclxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2FkZENvbXBvbmVudDxUIGV4dGVuZHMgTmFtZT4oXG4gIGFwcDogRmlyZWJhc2VBcHAsXG4gIGNvbXBvbmVudDogQ29tcG9uZW50PFQ+XG4pOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICAoYXBwIGFzIEZpcmViYXNlQXBwSW1wbCkuY29udGFpbmVyLmFkZENvbXBvbmVudChjb21wb25lbnQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgYENvbXBvbmVudCAke2NvbXBvbmVudC5uYW1lfSBmYWlsZWQgdG8gcmVnaXN0ZXIgd2l0aCBGaXJlYmFzZUFwcCAke2FwcC5uYW1lfWAsXG4gICAgICBlXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9hZGRPck92ZXJ3cml0ZUNvbXBvbmVudChcbiAgYXBwOiBGaXJlYmFzZUFwcCxcbiAgY29tcG9uZW50OiBDb21wb25lbnRcbik6IHZvaWQge1xuICAoYXBwIGFzIEZpcmViYXNlQXBwSW1wbCkuY29udGFpbmVyLmFkZE9yT3ZlcndyaXRlQ29tcG9uZW50KGNvbXBvbmVudCk7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBjb21wb25lbnQgLSB0aGUgY29tcG9uZW50IHRvIHJlZ2lzdGVyXG4gKiBAcmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgY29tcG9uZW50IGlzIHJlZ2lzdGVyZWQgc3VjY2Vzc2Z1bGx5XG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfcmVnaXN0ZXJDb21wb25lbnQ8VCBleHRlbmRzIE5hbWU+KFxuICBjb21wb25lbnQ6IENvbXBvbmVudDxUPlxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNvbXBvbmVudE5hbWUgPSBjb21wb25lbnQubmFtZTtcbiAgaWYgKF9jb21wb25lbnRzLmhhcyhjb21wb25lbnROYW1lKSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgIGBUaGVyZSB3ZXJlIG11bHRpcGxlIGF0dGVtcHRzIHRvIHJlZ2lzdGVyIGNvbXBvbmVudCAke2NvbXBvbmVudE5hbWV9LmBcbiAgICApO1xuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgX2NvbXBvbmVudHMuc2V0KGNvbXBvbmVudE5hbWUsIGNvbXBvbmVudCk7XG5cbiAgLy8gYWRkIHRoZSBjb21wb25lbnQgdG8gZXhpc3RpbmcgYXBwIGluc3RhbmNlc1xuICBmb3IgKGNvbnN0IGFwcCBvZiBfYXBwcy52YWx1ZXMoKSkge1xuICAgIF9hZGRDb21wb25lbnQoYXBwIGFzIEZpcmViYXNlQXBwSW1wbCwgY29tcG9uZW50KTtcbiAgfVxuXG4gIGZvciAoY29uc3Qgc2VydmVyQXBwIG9mIF9zZXJ2ZXJBcHBzLnZhbHVlcygpKSB7XG4gICAgX2FkZENvbXBvbmVudChzZXJ2ZXJBcHAgYXMgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsLCBjb21wb25lbnQpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBhcHAgLSBGaXJlYmFzZUFwcCBpbnN0YW5jZVxuICogQHBhcmFtIG5hbWUgLSBzZXJ2aWNlIG5hbWVcbiAqXG4gKiBAcmV0dXJucyB0aGUgcHJvdmlkZXIgZm9yIHRoZSBzZXJ2aWNlIHdpdGggdGhlIG1hdGNoaW5nIG5hbWVcbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9nZXRQcm92aWRlcjxUIGV4dGVuZHMgTmFtZT4oXG4gIGFwcDogRmlyZWJhc2VBcHAsXG4gIG5hbWU6IFRcbik6IFByb3ZpZGVyPFQ+IHtcbiAgY29uc3QgaGVhcnRiZWF0Q29udHJvbGxlciA9IChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsKS5jb250YWluZXJcbiAgICAuZ2V0UHJvdmlkZXIoJ2hlYXJ0YmVhdCcpXG4gICAgLmdldEltbWVkaWF0ZSh7IG9wdGlvbmFsOiB0cnVlIH0pO1xuICBpZiAoaGVhcnRiZWF0Q29udHJvbGxlcikge1xuICAgIHZvaWQgaGVhcnRiZWF0Q29udHJvbGxlci50cmlnZ2VySGVhcnRiZWF0KCk7XG4gIH1cbiAgcmV0dXJuIChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsKS5jb250YWluZXIuZ2V0UHJvdmlkZXIobmFtZSk7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBhcHAgLSBGaXJlYmFzZUFwcCBpbnN0YW5jZVxuICogQHBhcmFtIG5hbWUgLSBzZXJ2aWNlIG5hbWVcbiAqIEBwYXJhbSBpbnN0YW5jZUlkZW50aWZpZXIgLSBzZXJ2aWNlIGluc3RhbmNlIGlkZW50aWZpZXIgaW4gY2FzZSB0aGUgc2VydmljZSBzdXBwb3J0cyBtdWx0aXBsZSBpbnN0YW5jZXNcbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9yZW1vdmVTZXJ2aWNlSW5zdGFuY2U8VCBleHRlbmRzIE5hbWU+KFxuICBhcHA6IEZpcmViYXNlQXBwLFxuICBuYW1lOiBULFxuICBpbnN0YW5jZUlkZW50aWZpZXI6IHN0cmluZyA9IERFRkFVTFRfRU5UUllfTkFNRVxuKTogdm9pZCB7XG4gIF9nZXRQcm92aWRlcihhcHAsIG5hbWUpLmNsZWFySW5zdGFuY2UoaW5zdGFuY2VJZGVudGlmaWVyKTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIG9iaiAtIGFuIG9iamVjdCBvZiB0eXBlIEZpcmViYXNlQXBwLCBGaXJlYmFzZU9wdGlvbnMgb3IgRmlyZWJhc2VBcHBTZXR0aW5ncy5cbiAqXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBwcm92aWRlIG9iamVjdCBpcyBvZiB0eXBlIEZpcmViYXNlQXBwLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2lzRmlyZWJhc2VBcHAoXG4gIG9iajogRmlyZWJhc2VBcHAgfCBGaXJlYmFzZU9wdGlvbnMgfCBGaXJlYmFzZUFwcFNldHRpbmdzXG4pOiBvYmogaXMgRmlyZWJhc2VBcHAge1xuICByZXR1cm4gKG9iaiBhcyBGaXJlYmFzZUFwcCkub3B0aW9ucyAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gb2JqIC0gYW4gb2JqZWN0IG9mIHR5cGUgRmlyZWJhc2VBcHAsIEZpcmViYXNlT3B0aW9ucyBvciBGaXJlYmFzZUFwcFNldHRpbmdzLlxuICpcbiAqIEByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGVkIG9iamVjdCBpcyBvZiB0eXBlIEZpcmViYXNlU2VydmVyQXBwSW1wbC5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9pc0ZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MoXG4gIG9iajogRmlyZWJhc2VBcHAgfCBGaXJlYmFzZU9wdGlvbnMgfCBGaXJlYmFzZUFwcFNldHRpbmdzXG4pOiBvYmogaXMgRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncyB7XG4gIGlmIChfaXNGaXJlYmFzZUFwcChvYmopKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiAoXG4gICAgJ2F1dGhJZFRva2VuJyBpbiBvYmogfHxcbiAgICAnYXBwQ2hlY2tUb2tlbicgaW4gb2JqIHx8XG4gICAgJ3JlbGVhc2VPbkRlcmVmJyBpbiBvYmogfHxcbiAgICAnYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkJyBpbiBvYmpcbiAgKTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIG9iaiAtIGFuIG9iamVjdCBvZiB0eXBlIEZpcmViYXNlQXBwLlxuICpcbiAqIEByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGVkIG9iamVjdCBpcyBvZiB0eXBlIEZpcmViYXNlU2VydmVyQXBwSW1wbC5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9pc0ZpcmViYXNlU2VydmVyQXBwKFxuICBvYmo6IEZpcmViYXNlQXBwIHwgRmlyZWJhc2VTZXJ2ZXJBcHAgfCBudWxsIHwgdW5kZWZpbmVkXG4pOiBvYmogaXMgRmlyZWJhc2VTZXJ2ZXJBcHAge1xuICBpZiAob2JqID09PSBudWxsIHx8IG9iaiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiAob2JqIGFzIEZpcmViYXNlU2VydmVyQXBwKS5zZXR0aW5ncyAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFRlc3Qgb25seVxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2NsZWFyQ29tcG9uZW50cygpOiB2b2lkIHtcbiAgX2NvbXBvbmVudHMuY2xlYXIoKTtcbn1cblxuLyoqXG4gKiBFeHBvcnRlZCBpbiBvcmRlciB0byBiZSB1c2VkIGluIGFwcC1jb21wYXQgcGFja2FnZVxuICovXG5leHBvcnQgeyBERUZBVUxUX0VOVFJZX05BTUUgYXMgX0RFRkFVTFRfRU5UUllfTkFNRSB9O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEVycm9yRmFjdG9yeSwgRXJyb3JNYXAgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmV4cG9ydCBjb25zdCBlbnVtIEFwcEVycm9yIHtcbiAgTk9fQVBQID0gJ25vLWFwcCcsXG4gIEJBRF9BUFBfTkFNRSA9ICdiYWQtYXBwLW5hbWUnLFxuICBEVVBMSUNBVEVfQVBQID0gJ2R1cGxpY2F0ZS1hcHAnLFxuICBBUFBfREVMRVRFRCA9ICdhcHAtZGVsZXRlZCcsXG4gIFNFUlZFUl9BUFBfREVMRVRFRCA9ICdzZXJ2ZXItYXBwLWRlbGV0ZWQnLFxuICBOT19PUFRJT05TID0gJ25vLW9wdGlvbnMnLFxuICBJTlZBTElEX0FQUF9BUkdVTUVOVCA9ICdpbnZhbGlkLWFwcC1hcmd1bWVudCcsXG4gIElOVkFMSURfTE9HX0FSR1VNRU5UID0gJ2ludmFsaWQtbG9nLWFyZ3VtZW50JyxcbiAgSURCX09QRU4gPSAnaWRiLW9wZW4nLFxuICBJREJfR0VUID0gJ2lkYi1nZXQnLFxuICBJREJfV1JJVEUgPSAnaWRiLXNldCcsXG4gIElEQl9ERUxFVEUgPSAnaWRiLWRlbGV0ZScsXG4gIEZJTkFMSVpBVElPTl9SRUdJU1RSWV9OT1RfU1VQUE9SVEVEID0gJ2ZpbmFsaXphdGlvbi1yZWdpc3RyeS1ub3Qtc3VwcG9ydGVkJyxcbiAgSU5WQUxJRF9TRVJWRVJfQVBQX0VOVklST05NRU5UID0gJ2ludmFsaWQtc2VydmVyLWFwcC1lbnZpcm9ubWVudCdcbn1cblxuY29uc3QgRVJST1JTOiBFcnJvck1hcDxBcHBFcnJvcj4gPSB7XG4gIFtBcHBFcnJvci5OT19BUFBdOlxuICAgIFwiTm8gRmlyZWJhc2UgQXBwICd7JGFwcE5hbWV9JyBoYXMgYmVlbiBjcmVhdGVkIC0gXCIgK1xuICAgICdjYWxsIGluaXRpYWxpemVBcHAoKSBmaXJzdCcsXG4gIFtBcHBFcnJvci5CQURfQVBQX05BTUVdOiBcIklsbGVnYWwgQXBwIG5hbWU6ICd7JGFwcE5hbWV9J1wiLFxuICBbQXBwRXJyb3IuRFVQTElDQVRFX0FQUF06XG4gICAgXCJGaXJlYmFzZSBBcHAgbmFtZWQgJ3skYXBwTmFtZX0nIGFscmVhZHkgZXhpc3RzIHdpdGggZGlmZmVyZW50IG9wdGlvbnMgb3IgY29uZmlnXCIsXG4gIFtBcHBFcnJvci5BUFBfREVMRVRFRF06IFwiRmlyZWJhc2UgQXBwIG5hbWVkICd7JGFwcE5hbWV9JyBhbHJlYWR5IGRlbGV0ZWRcIixcbiAgW0FwcEVycm9yLlNFUlZFUl9BUFBfREVMRVRFRF06ICdGaXJlYmFzZSBTZXJ2ZXIgQXBwIGhhcyBiZWVuIGRlbGV0ZWQnLFxuICBbQXBwRXJyb3IuTk9fT1BUSU9OU106XG4gICAgJ05lZWQgdG8gcHJvdmlkZSBvcHRpb25zLCB3aGVuIG5vdCBiZWluZyBkZXBsb3llZCB0byBob3N0aW5nIHZpYSBzb3VyY2UuJyxcbiAgW0FwcEVycm9yLklOVkFMSURfQVBQX0FSR1VNRU5UXTpcbiAgICAnZmlyZWJhc2UueyRhcHBOYW1lfSgpIHRha2VzIGVpdGhlciBubyBhcmd1bWVudCBvciBhICcgK1xuICAgICdGaXJlYmFzZSBBcHAgaW5zdGFuY2UuJyxcbiAgW0FwcEVycm9yLklOVkFMSURfTE9HX0FSR1VNRU5UXTpcbiAgICAnRmlyc3QgYXJndW1lbnQgdG8gYG9uTG9nYCBtdXN0IGJlIG51bGwgb3IgYSBmdW5jdGlvbi4nLFxuICBbQXBwRXJyb3IuSURCX09QRU5dOlxuICAgICdFcnJvciB0aHJvd24gd2hlbiBvcGVuaW5nIEluZGV4ZWREQi4gT3JpZ2luYWwgZXJyb3I6IHskb3JpZ2luYWxFcnJvck1lc3NhZ2V9LicsXG4gIFtBcHBFcnJvci5JREJfR0VUXTpcbiAgICAnRXJyb3IgdGhyb3duIHdoZW4gcmVhZGluZyBmcm9tIEluZGV4ZWREQi4gT3JpZ2luYWwgZXJyb3I6IHskb3JpZ2luYWxFcnJvck1lc3NhZ2V9LicsXG4gIFtBcHBFcnJvci5JREJfV1JJVEVdOlxuICAgICdFcnJvciB0aHJvd24gd2hlbiB3cml0aW5nIHRvIEluZGV4ZWREQi4gT3JpZ2luYWwgZXJyb3I6IHskb3JpZ2luYWxFcnJvck1lc3NhZ2V9LicsXG4gIFtBcHBFcnJvci5JREJfREVMRVRFXTpcbiAgICAnRXJyb3IgdGhyb3duIHdoZW4gZGVsZXRpbmcgZnJvbSBJbmRleGVkREIuIE9yaWdpbmFsIGVycm9yOiB7JG9yaWdpbmFsRXJyb3JNZXNzYWdlfS4nLFxuICBbQXBwRXJyb3IuRklOQUxJWkFUSU9OX1JFR0lTVFJZX05PVF9TVVBQT1JURURdOlxuICAgICdGaXJlYmFzZVNlcnZlckFwcCBkZWxldGVPbkRlcmVmIGZpZWxkIGRlZmluZWQgYnV0IHRoZSBKUyBydW50aW1lIGRvZXMgbm90IHN1cHBvcnQgRmluYWxpemF0aW9uUmVnaXN0cnkuJyxcbiAgW0FwcEVycm9yLklOVkFMSURfU0VSVkVSX0FQUF9FTlZJUk9OTUVOVF06XG4gICAgJ0ZpcmViYXNlU2VydmVyQXBwIGlzIG5vdCBmb3IgdXNlIGluIGJyb3dzZXIgZW52aXJvbm1lbnRzLidcbn07XG5cbmludGVyZmFjZSBFcnJvclBhcmFtcyB7XG4gIFtBcHBFcnJvci5OT19BUFBdOiB7IGFwcE5hbWU6IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuQkFEX0FQUF9OQU1FXTogeyBhcHBOYW1lOiBzdHJpbmcgfTtcbiAgW0FwcEVycm9yLkRVUExJQ0FURV9BUFBdOiB7IGFwcE5hbWU6IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuQVBQX0RFTEVURURdOiB7IGFwcE5hbWU6IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuSU5WQUxJRF9BUFBfQVJHVU1FTlRdOiB7IGFwcE5hbWU6IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuSURCX09QRU5dOiB7IG9yaWdpbmFsRXJyb3JNZXNzYWdlPzogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5JREJfR0VUXTogeyBvcmlnaW5hbEVycm9yTWVzc2FnZT86IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuSURCX1dSSVRFXTogeyBvcmlnaW5hbEVycm9yTWVzc2FnZT86IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuSURCX0RFTEVURV06IHsgb3JpZ2luYWxFcnJvck1lc3NhZ2U/OiBzdHJpbmcgfTtcbiAgW0FwcEVycm9yLkZJTkFMSVpBVElPTl9SRUdJU1RSWV9OT1RfU1VQUE9SVEVEXTogeyBhcHBOYW1lPzogc3RyaW5nIH07XG59XG5cbmV4cG9ydCBjb25zdCBFUlJPUl9GQUNUT1JZID0gbmV3IEVycm9yRmFjdG9yeTxBcHBFcnJvciwgRXJyb3JQYXJhbXM+KFxuICAnYXBwJyxcbiAgJ0ZpcmViYXNlJyxcbiAgRVJST1JTXG4pO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEZpcmViYXNlQXBwLFxuICBGaXJlYmFzZU9wdGlvbnMsXG4gIEZpcmViYXNlQXBwU2V0dGluZ3Ncbn0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50Q29udGFpbmVyLFxuICBDb21wb25lbnQsXG4gIENvbXBvbmVudFR5cGVcbn0gZnJvbSAnQGZpcmViYXNlL2NvbXBvbmVudCc7XG5pbXBvcnQgeyBFUlJPUl9GQUNUT1JZLCBBcHBFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcblxuZXhwb3J0IGNsYXNzIEZpcmViYXNlQXBwSW1wbCBpbXBsZW1lbnRzIEZpcmViYXNlQXBwIHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9vcHRpb25zOiBGaXJlYmFzZU9wdGlvbnM7XG4gIHByb3RlY3RlZCByZWFkb25seSBfbmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogT3JpZ2luYWwgY29uZmlnIHZhbHVlcyBwYXNzZWQgaW4gYXMgYSBjb25zdHJ1Y3RvciBwYXJhbWV0ZXIuXG4gICAqIEl0IGlzIG9ubHkgdXNlZCB0byBjb21wYXJlIHdpdGggYW5vdGhlciBjb25maWcgb2JqZWN0IHRvIHN1cHBvcnQgaWRlbXBvdGVudCBpbml0aWFsaXplQXBwKCkuXG4gICAqXG4gICAqIFVwZGF0aW5nIGF1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCBvbiB0aGUgQXBwIGluc3RhbmNlIHdpbGwgbm90IGNoYW5nZSBpdHMgdmFsdWUgaW4gX2NvbmZpZy5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2NvbmZpZzogUmVxdWlyZWQ8RmlyZWJhc2VBcHBTZXR0aW5ncz47XG4gIHByaXZhdGUgX2F1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZDogYm9vbGVhbjtcbiAgcHJvdGVjdGVkIF9pc0RlbGV0ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWFkb25seSBfY29udGFpbmVyOiBDb21wb25lbnRDb250YWluZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb3B0aW9uczogRmlyZWJhc2VPcHRpb25zLFxuICAgIGNvbmZpZzogUmVxdWlyZWQ8RmlyZWJhc2VBcHBTZXR0aW5ncz4sXG4gICAgY29udGFpbmVyOiBDb21wb25lbnRDb250YWluZXJcbiAgKSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IHsgLi4ub3B0aW9ucyB9O1xuICAgIHRoaXMuX2NvbmZpZyA9IHsgLi4uY29uZmlnIH07XG4gICAgdGhpcy5fbmFtZSA9IGNvbmZpZy5uYW1lO1xuICAgIHRoaXMuX2F1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCA9XG4gICAgICBjb25maWcuYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkO1xuICAgIHRoaXMuX2NvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICB0aGlzLmNvbnRhaW5lci5hZGRDb21wb25lbnQoXG4gICAgICBuZXcgQ29tcG9uZW50KCdhcHAnLCAoKSA9PiB0aGlzLCBDb21wb25lbnRUeXBlLlBVQkxJQylcbiAgICApO1xuICB9XG5cbiAgZ2V0IGF1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICB0aGlzLmNoZWNrRGVzdHJveWVkKCk7XG4gICAgcmV0dXJuIHRoaXMuX2F1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZDtcbiAgfVxuXG4gIHNldCBhdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQodmFsOiBib29sZWFuKSB7XG4gICAgdGhpcy5jaGVja0Rlc3Ryb3llZCgpO1xuICAgIHRoaXMuX2F1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCA9IHZhbDtcbiAgfVxuXG4gIGdldCBuYW1lKCk6IHN0cmluZyB7XG4gICAgdGhpcy5jaGVja0Rlc3Ryb3llZCgpO1xuICAgIHJldHVybiB0aGlzLl9uYW1lO1xuICB9XG5cbiAgZ2V0IG9wdGlvbnMoKTogRmlyZWJhc2VPcHRpb25zIHtcbiAgICB0aGlzLmNoZWNrRGVzdHJveWVkKCk7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cblxuICBnZXQgY29uZmlnKCk6IFJlcXVpcmVkPEZpcmViYXNlQXBwU2V0dGluZ3M+IHtcbiAgICB0aGlzLmNoZWNrRGVzdHJveWVkKCk7XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZztcbiAgfVxuXG4gIGdldCBjb250YWluZXIoKTogQ29tcG9uZW50Q29udGFpbmVyIHtcbiAgICByZXR1cm4gdGhpcy5fY29udGFpbmVyO1xuICB9XG5cbiAgZ2V0IGlzRGVsZXRlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faXNEZWxldGVkO1xuICB9XG5cbiAgc2V0IGlzRGVsZXRlZCh2YWw6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9pc0RlbGV0ZWQgPSB2YWw7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiB3aWxsIHRocm93IGFuIEVycm9yIGlmIHRoZSBBcHAgaGFzIGFscmVhZHkgYmVlbiBkZWxldGVkIC1cbiAgICogdXNlIGJlZm9yZSBwZXJmb3JtaW5nIEFQSSBhY3Rpb25zIG9uIHRoZSBBcHAuXG4gICAqL1xuICBwcm90ZWN0ZWQgY2hlY2tEZXN0cm95ZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNEZWxldGVkKSB7XG4gICAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5BUFBfREVMRVRFRCwgeyBhcHBOYW1lOiB0aGlzLl9uYW1lIH0pO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEZpcmViYXNlQXBwU2V0dGluZ3MsXG4gIEZpcmViYXNlU2VydmVyQXBwLFxuICBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzLFxuICBGaXJlYmFzZU9wdGlvbnNcbn0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHsgZGVsZXRlQXBwLCByZWdpc3RlclZlcnNpb24gfSBmcm9tICcuL2FwaSc7XG5pbXBvcnQgeyBDb21wb25lbnRDb250YWluZXIgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IEZpcmViYXNlQXBwSW1wbCB9IGZyb20gJy4vZmlyZWJhc2VBcHAnO1xuaW1wb3J0IHsgRVJST1JfRkFDVE9SWSwgQXBwRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBuYW1lIGFzIHBhY2thZ2VOYW1lLCB2ZXJzaW9uIH0gZnJvbSAnLi4vcGFja2FnZS5qc29uJztcbmltcG9ydCB7IGJhc2U2NERlY29kZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuLy8gUGFyc2UgdGhlIHRva2VuIGFuZCBjaGVjayB0byBzZWUgaWYgdGhlIGBleHBgIGNsYWltIGlzIGluIHRoZSBmdXR1cmUuXG4vLyBSZXBvcnRzIGFuIGVycm9yIHRvIHRoZSBjb25zb2xlIGlmIHRoZSB0b2tlbiBvciBjbGFpbSBjb3VsZCBub3QgYmUgcGFyc2VkLCBvciBpZiBgZXhwYCBpcyBpblxuLy8gdGhlIHBhc3QuXG5mdW5jdGlvbiB2YWxpZGF0ZVRva2VuVFRMKGJhc2U2NFRva2VuOiBzdHJpbmcsIHRva2VuTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHNlY29uZFBhcnQgPSBiYXNlNjREZWNvZGUoYmFzZTY0VG9rZW4uc3BsaXQoJy4nKVsxXSk7XG4gIGlmIChzZWNvbmRQYXJ0ID09PSBudWxsKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIGBGaXJlYmFzZVNlcnZlckFwcCAke3Rva2VuTmFtZX0gaXMgaW52YWxpZDogc2Vjb25kIHBhcnQgY291bGQgbm90IGJlIHBhcnNlZC5gXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgZXhwQ2xhaW0gPSBKU09OLnBhcnNlKHNlY29uZFBhcnQpLmV4cDtcbiAgaWYgKGV4cENsYWltID09PSB1bmRlZmluZWQpIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgYEZpcmViYXNlU2VydmVyQXBwICR7dG9rZW5OYW1lfSBpcyBpbnZhbGlkOiBleHBpcmF0aW9uIGNsYWltIGNvdWxkIG5vdCBiZSBwYXJzZWRgXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgZXhwID0gSlNPTi5wYXJzZShzZWNvbmRQYXJ0KS5leHAgKiAxMDAwO1xuICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgY29uc3QgZGlmZiA9IGV4cCAtIG5vdztcbiAgaWYgKGRpZmYgPD0gMCkge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBgRmlyZWJhc2VTZXJ2ZXJBcHAgJHt0b2tlbk5hbWV9IGlzIGludmFsaWQ6IHRoZSB0b2tlbiBoYXMgZXhwaXJlZC5gXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsXG4gIGV4dGVuZHMgRmlyZWJhc2VBcHBJbXBsXG4gIGltcGxlbWVudHMgRmlyZWJhc2VTZXJ2ZXJBcHBcbntcbiAgcHJpdmF0ZSByZWFkb25seSBfc2VydmVyQ29uZmlnOiBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzO1xuICBwcml2YXRlIF9maW5hbGl6YXRpb25SZWdpc3RyeTogRmluYWxpemF0aW9uUmVnaXN0cnk8b2JqZWN0PiB8IG51bGw7XG4gIHByaXZhdGUgX3JlZkNvdW50OiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgb3B0aW9uczogRmlyZWJhc2VPcHRpb25zIHwgRmlyZWJhc2VBcHBJbXBsLFxuICAgIHNlcnZlckNvbmZpZzogRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncyxcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgY29udGFpbmVyOiBDb21wb25lbnRDb250YWluZXJcbiAgKSB7XG4gICAgLy8gQnVpbGQgY29uZmlndXJhdGlvbiBwYXJhbWV0ZXJzIGZvciB0aGUgRmlyZWJhc2VBcHBJbXBsIGJhc2UgY2xhc3MuXG4gICAgY29uc3QgYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkID1cbiAgICAgIHNlcnZlckNvbmZpZy5hdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IHNlcnZlckNvbmZpZy5hdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWRcbiAgICAgICAgOiB0cnVlO1xuXG4gICAgLy8gQ3JlYXRlIHRoZSBGaXJlYmFzZUFwcFNldHRpbmdzIG9iamVjdCBmb3IgdGhlIEZpcmViYXNlQXBwSW1wIGNvbnN0cnVjdG9yLlxuICAgIGNvbnN0IGNvbmZpZzogUmVxdWlyZWQ8RmlyZWJhc2VBcHBTZXR0aW5ncz4gPSB7XG4gICAgICBuYW1lLFxuICAgICAgYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkXG4gICAgfTtcblxuICAgIGlmICgob3B0aW9ucyBhcyBGaXJlYmFzZU9wdGlvbnMpLmFwaUtleSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBDb25zdHJ1Y3QgdGhlIHBhcmVudCBGaXJlYmFzZUFwcEltcCBvYmplY3QuXG4gICAgICBzdXBlcihvcHRpb25zIGFzIEZpcmViYXNlT3B0aW9ucywgY29uZmlnLCBjb250YWluZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBhcHBJbXBsOiBGaXJlYmFzZUFwcEltcGwgPSBvcHRpb25zIGFzIEZpcmViYXNlQXBwSW1wbDtcbiAgICAgIHN1cGVyKGFwcEltcGwub3B0aW9ucywgY29uZmlnLCBjb250YWluZXIpO1xuICAgIH1cblxuICAgIC8vIE5vdyBjb25zdHJ1Y3QgdGhlIGRhdGEgZm9yIHRoZSBGaXJlYmFzZVNlcnZlckFwcEltcGwuXG4gICAgdGhpcy5fc2VydmVyQ29uZmlnID0ge1xuICAgICAgYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkLFxuICAgICAgLi4uc2VydmVyQ29uZmlnXG4gICAgfTtcblxuICAgIC8vIEVuc3VyZSB0aGF0IHRoZSBjdXJyZW50IHRpbWUgaXMgd2l0aGluIHRoZSBgYXV0aElkdG9rZW5gIHdpbmRvdyBvZiB2YWxpZGl0eS5cbiAgICBpZiAodGhpcy5fc2VydmVyQ29uZmlnLmF1dGhJZFRva2VuKSB7XG4gICAgICB2YWxpZGF0ZVRva2VuVFRMKHRoaXMuX3NlcnZlckNvbmZpZy5hdXRoSWRUb2tlbiwgJ2F1dGhJZFRva2VuJyk7XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIHRoYXQgdGhlIGN1cnJlbnQgdGltZSBpcyB3aXRoaW4gdGhlIGBhcHBDaGVja1Rva2VuYCB3aW5kb3cgb2YgdmFsaWRpdHkuXG4gICAgaWYgKHRoaXMuX3NlcnZlckNvbmZpZy5hcHBDaGVja1Rva2VuKSB7XG4gICAgICB2YWxpZGF0ZVRva2VuVFRMKHRoaXMuX3NlcnZlckNvbmZpZy5hcHBDaGVja1Rva2VuLCAnYXBwQ2hlY2tUb2tlbicpO1xuICAgIH1cblxuICAgIHRoaXMuX2ZpbmFsaXphdGlvblJlZ2lzdHJ5ID0gbnVsbDtcbiAgICBpZiAodHlwZW9mIEZpbmFsaXphdGlvblJlZ2lzdHJ5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5fZmluYWxpemF0aW9uUmVnaXN0cnkgPSBuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkoKCkgPT4ge1xuICAgICAgICB0aGlzLmF1dG9tYXRpY0NsZWFudXAoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuX3JlZkNvdW50ID0gMDtcbiAgICB0aGlzLmluY1JlZkNvdW50KHRoaXMuX3NlcnZlckNvbmZpZy5yZWxlYXNlT25EZXJlZik7XG5cbiAgICAvLyBEbyBub3QgcmV0YWluIGEgaGFyZCByZWZlcmVuY2UgdG8gdGhlIGRyZWYgb2JqZWN0LCBvdGhlcndpc2UgdGhlIEZpbmFsaXphdGlvblJlZ2lzdHJ5XG4gICAgLy8gd2lsbCBuZXZlciB0cmlnZ2VyLlxuICAgIHRoaXMuX3NlcnZlckNvbmZpZy5yZWxlYXNlT25EZXJlZiA9IHVuZGVmaW5lZDtcbiAgICBzZXJ2ZXJDb25maWcucmVsZWFzZU9uRGVyZWYgPSB1bmRlZmluZWQ7XG5cbiAgICByZWdpc3RlclZlcnNpb24ocGFja2FnZU5hbWUsIHZlcnNpb24sICdzZXJ2ZXJhcHAnKTtcbiAgfVxuXG4gIHRvSlNPTigpOiB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBnZXQgcmVmQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fcmVmQ291bnQ7XG4gIH1cblxuICAvLyBJbmNyZW1lbnQgdGhlIHJlZmVyZW5jZSBjb3VudCBvZiB0aGlzIHNlcnZlciBhcHAuIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCwgcmVnaXN0ZXIgaXRcbiAgLy8gd2l0aCB0aGUgZmluYWxpemF0aW9uIHJlZ2lzdHJ5LlxuICBpbmNSZWZDb3VudChvYmo6IG9iamVjdCB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzRGVsZXRlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9yZWZDb3VudCsrO1xuICAgIGlmIChvYmogIT09IHVuZGVmaW5lZCAmJiB0aGlzLl9maW5hbGl6YXRpb25SZWdpc3RyeSAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5fZmluYWxpemF0aW9uUmVnaXN0cnkucmVnaXN0ZXIob2JqLCB0aGlzKTtcbiAgICB9XG4gIH1cblxuICAvLyBEZWNyZW1lbnQgdGhlIHJlZmVyZW5jZSBjb3VudC5cbiAgZGVjUmVmQ291bnQoKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5pc0RlbGV0ZWQpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICByZXR1cm4gLS10aGlzLl9yZWZDb3VudDtcbiAgfVxuXG4gIC8vIEludm9rZWQgYnkgdGhlIEZpbmFsaXphdGlvblJlZ2lzdHJ5IGNhbGxiYWNrIHRvIG5vdGUgdGhhdCB0aGlzIGFwcCBzaG91bGQgZ28gdGhyb3VnaCBpdHNcbiAgLy8gcmVmZXJlbmNlIGNvdW50cyBhbmQgZGVsZXRlIGl0c2VsZiBpZiBubyByZWZlcmVuY2UgY291bnQgcmVtYWluLiBUaGUgY29vcmRpbmF0aW5nIGxvZ2ljIHRoYXRcbiAgLy8gaGFuZGxlcyB0aGlzIGlzIGluIGRlbGV0ZUFwcCguLi4pLlxuICBwcml2YXRlIGF1dG9tYXRpY0NsZWFudXAoKTogdm9pZCB7XG4gICAgdm9pZCBkZWxldGVBcHAodGhpcyk7XG4gIH1cblxuICBnZXQgc2V0dGluZ3MoKTogRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncyB7XG4gICAgdGhpcy5jaGVja0Rlc3Ryb3llZCgpO1xuICAgIHJldHVybiB0aGlzLl9zZXJ2ZXJDb25maWc7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiB3aWxsIHRocm93IGFuIEVycm9yIGlmIHRoZSBBcHAgaGFzIGFscmVhZHkgYmVlbiBkZWxldGVkIC1cbiAgICogdXNlIGJlZm9yZSBwZXJmb3JtaW5nIEFQSSBhY3Rpb25zIG9uIHRoZSBBcHAuXG4gICAqL1xuICBwcm90ZWN0ZWQgY2hlY2tEZXN0cm95ZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNEZWxldGVkKSB7XG4gICAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5TRVJWRVJfQVBQX0RFTEVURUQpO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEZpcmViYXNlQXBwLFxuICBGaXJlYmFzZVNlcnZlckFwcCxcbiAgRmlyZWJhc2VPcHRpb25zLFxuICBGaXJlYmFzZUFwcFNldHRpbmdzLFxuICBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzXG59IGZyb20gJy4vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IERFRkFVTFRfRU5UUllfTkFNRSwgUExBVEZPUk1fTE9HX1NUUklORyB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IEVSUk9SX0ZBQ1RPUlksIEFwcEVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50Q29udGFpbmVyLFxuICBDb21wb25lbnQsXG4gIE5hbWUsXG4gIENvbXBvbmVudFR5cGVcbn0gZnJvbSAnQGZpcmViYXNlL2NvbXBvbmVudCc7XG5pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi4vLi4vZmlyZWJhc2UvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IEZpcmViYXNlQXBwSW1wbCB9IGZyb20gJy4vZmlyZWJhc2VBcHAnO1xuaW1wb3J0IHsgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsIH0gZnJvbSAnLi9maXJlYmFzZVNlcnZlckFwcCc7XG5pbXBvcnQge1xuICBfYXBwcyxcbiAgX2NvbXBvbmVudHMsXG4gIF9pc0ZpcmViYXNlQXBwLFxuICBfaXNGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzLFxuICBfcmVnaXN0ZXJDb21wb25lbnQsXG4gIF9zZXJ2ZXJBcHBzXG59IGZyb20gJy4vaW50ZXJuYWwnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHtcbiAgTG9nTGV2ZWxTdHJpbmcsXG4gIHNldExvZ0xldmVsIGFzIHNldExvZ0xldmVsSW1wbCxcbiAgTG9nQ2FsbGJhY2ssXG4gIExvZ09wdGlvbnMsXG4gIHNldFVzZXJMb2dIYW5kbGVyXG59IGZyb20gJ0BmaXJlYmFzZS9sb2dnZXInO1xuaW1wb3J0IHtcbiAgZGVlcEVxdWFsLFxuICBnZXREZWZhdWx0QXBwQ29uZmlnLFxuICBpc0Jyb3dzZXIsXG4gIGlzV2ViV29ya2VyXG59IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuLyoqXG4gKiBUaGUgY3VycmVudCBTREsgdmVyc2lvbi5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBTREtfVkVSU0lPTiA9IHZlcnNpb247XG5cbi8qKlxuICogQ3JlYXRlcyBhbmQgaW5pdGlhbGl6ZXMgYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZUFwcH0gaW5zdGFuY2UuXG4gKlxuICogU2VlXG4gKiB7QGxpbmtcbiAqICAgaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3Mvd2ViL3NldHVwI2FkZF9maXJlYmFzZV90b195b3VyX2FwcFxuICogICB8IEFkZCBGaXJlYmFzZSB0byB5b3VyIGFwcH0gYW5kXG4gKiB7QGxpbmtcbiAqICAgaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3Mvd2ViL3NldHVwI211bHRpcGxlLXByb2plY3RzXG4gKiAgIHwgSW5pdGlhbGl6ZSBtdWx0aXBsZSBwcm9qZWN0c30gZm9yIGRldGFpbGVkIGRvY3VtZW50YXRpb24uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqXG4gKiAvLyBJbml0aWFsaXplIGRlZmF1bHQgYXBwXG4gKiAvLyBSZXRyaWV2ZSB5b3VyIG93biBvcHRpb25zIHZhbHVlcyBieSBhZGRpbmcgYSB3ZWIgYXBwIG9uXG4gKiAvLyBodHRwczovL2NvbnNvbGUuZmlyZWJhc2UuZ29vZ2xlLmNvbVxuICogaW5pdGlhbGl6ZUFwcCh7XG4gKiAgIGFwaUtleTogXCJBSXphLi4uLlwiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQXV0aCAvIEdlbmVyYWwgVXNlXG4gKiAgIGF1dGhEb21haW46IFwiWU9VUl9BUFAuZmlyZWJhc2VhcHAuY29tXCIsICAgICAgICAgLy8gQXV0aCB3aXRoIHBvcHVwL3JlZGlyZWN0XG4gKiAgIGRhdGFiYXNlVVJMOiBcImh0dHBzOi8vWU9VUl9BUFAuZmlyZWJhc2Vpby5jb21cIiwgLy8gUmVhbHRpbWUgRGF0YWJhc2VcbiAqICAgc3RvcmFnZUJ1Y2tldDogXCJZT1VSX0FQUC5hcHBzcG90LmNvbVwiLCAgICAgICAgICAvLyBTdG9yYWdlXG4gKiAgIG1lc3NhZ2luZ1NlbmRlcklkOiBcIjEyMzQ1Njc4OVwiICAgICAgICAgICAgICAgICAgLy8gQ2xvdWQgTWVzc2FnaW5nXG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKlxuICogLy8gSW5pdGlhbGl6ZSBhbm90aGVyIGFwcFxuICogY29uc3Qgb3RoZXJBcHAgPSBpbml0aWFsaXplQXBwKHtcbiAqICAgZGF0YWJhc2VVUkw6IFwiaHR0cHM6Ly88T1RIRVJfREFUQUJBU0VfTkFNRT4uZmlyZWJhc2Vpby5jb21cIixcbiAqICAgc3RvcmFnZUJ1Y2tldDogXCI8T1RIRVJfU1RPUkFHRV9CVUNLRVQ+LmFwcHNwb3QuY29tXCJcbiAqIH0sIFwib3RoZXJBcHBcIik7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgdG8gY29uZmlndXJlIHRoZSBhcHAncyBzZXJ2aWNlcy5cbiAqIEBwYXJhbSBuYW1lIC0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgYXBwIHRvIGluaXRpYWxpemUuIElmIG5vIG5hbWVcbiAqICAgaXMgcHJvdmlkZWQsIHRoZSBkZWZhdWx0IGlzIGBcIltERUZBVUxUXVwiYC5cbiAqXG4gKiBAcmV0dXJucyBUaGUgaW5pdGlhbGl6ZWQgYXBwLlxuICpcbiAqIEB0aHJvd3MgSWYgdGhlIG9wdGlvbmFsIGBuYW1lYCBwYXJhbWV0ZXIgaXMgbWFsZm9ybWVkIG9yIGVtcHR5LlxuICpcbiAqIEB0aHJvd3MgSWYgYSBgRmlyZWJhc2VBcHBgIGFscmVhZHkgZXhpc3RzIHdpdGggdGhlIHNhbWUgbmFtZSBidXQgd2l0aCBhIGRpZmZlcmVudCBjb25maWd1cmF0aW9uLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVBcHAoXG4gIG9wdGlvbnM6IEZpcmViYXNlT3B0aW9ucyxcbiAgbmFtZT86IHN0cmluZ1xuKTogRmlyZWJhc2VBcHA7XG4vKipcbiAqIENyZWF0ZXMgYW5kIGluaXRpYWxpemVzIGEgRmlyZWJhc2VBcHAgaW5zdGFuY2UuXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25zIHRvIGNvbmZpZ3VyZSB0aGUgYXBwJ3Mgc2VydmljZXMuXG4gKiBAcGFyYW0gY29uZmlnIC0gRmlyZWJhc2VBcHAgQ29uZmlndXJhdGlvblxuICpcbiAqIEB0aHJvd3MgSWYge0BsaW5rIEZpcmViYXNlQXBwU2V0dGluZ3MubmFtZX0gaXMgZGVmaW5lZCBidXQgdGhlIHZhbHVlIGlzIG1hbGZvcm1lZCBvciBlbXB0eS5cbiAqXG4gKiBAdGhyb3dzIElmIGEgYEZpcmViYXNlQXBwYCBhbHJlYWR5IGV4aXN0cyB3aXRoIHRoZSBzYW1lIG5hbWUgYnV0IHdpdGggYSBkaWZmZXJlbnQgY29uZmlndXJhdGlvbi5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVBcHAoXG4gIG9wdGlvbnM6IEZpcmViYXNlT3B0aW9ucyxcbiAgY29uZmlnPzogRmlyZWJhc2VBcHBTZXR0aW5nc1xuKTogRmlyZWJhc2VBcHA7XG4vKipcbiAqIENyZWF0ZXMgYW5kIGluaXRpYWxpemVzIGEgRmlyZWJhc2VBcHAgaW5zdGFuY2UuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZUFwcCgpOiBGaXJlYmFzZUFwcDtcbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplQXBwKFxuICBfb3B0aW9ucz86IEZpcmViYXNlT3B0aW9ucyxcbiAgcmF3Q29uZmlnID0ge31cbik6IEZpcmViYXNlQXBwIHtcbiAgbGV0IG9wdGlvbnMgPSBfb3B0aW9ucztcblxuICBpZiAodHlwZW9mIHJhd0NvbmZpZyAhPT0gJ29iamVjdCcpIHtcbiAgICBjb25zdCBuYW1lID0gcmF3Q29uZmlnO1xuICAgIHJhd0NvbmZpZyA9IHsgbmFtZSB9O1xuICB9XG5cbiAgY29uc3QgY29uZmlnOiBSZXF1aXJlZDxGaXJlYmFzZUFwcFNldHRpbmdzPiA9IHtcbiAgICBuYW1lOiBERUZBVUxUX0VOVFJZX05BTUUsXG4gICAgYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkOiB0cnVlLFxuICAgIC4uLnJhd0NvbmZpZ1xuICB9O1xuICBjb25zdCBuYW1lID0gY29uZmlnLm5hbWU7XG5cbiAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJyB8fCAhbmFtZSkge1xuICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLkJBRF9BUFBfTkFNRSwge1xuICAgICAgYXBwTmFtZTogU3RyaW5nKG5hbWUpXG4gICAgfSk7XG4gIH1cblxuICBvcHRpb25zIHx8PSBnZXREZWZhdWx0QXBwQ29uZmlnKCk7XG5cbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuTk9fT1BUSU9OUyk7XG4gIH1cblxuICBjb25zdCBleGlzdGluZ0FwcCA9IF9hcHBzLmdldChuYW1lKSBhcyBGaXJlYmFzZUFwcEltcGw7XG4gIGlmIChleGlzdGluZ0FwcCkge1xuICAgIC8vIHJldHVybiB0aGUgZXhpc3RpbmcgYXBwIGlmIG9wdGlvbnMgYW5kIGNvbmZpZyBkZWVwIGVxdWFsIHRoZSBvbmVzIGluIHRoZSBleGlzdGluZyBhcHAuXG4gICAgaWYgKFxuICAgICAgZGVlcEVxdWFsKG9wdGlvbnMsIGV4aXN0aW5nQXBwLm9wdGlvbnMpICYmXG4gICAgICBkZWVwRXF1YWwoY29uZmlnLCBleGlzdGluZ0FwcC5jb25maWcpXG4gICAgKSB7XG4gICAgICByZXR1cm4gZXhpc3RpbmdBcHA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLkRVUExJQ0FURV9BUFAsIHsgYXBwTmFtZTogbmFtZSB9KTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBjb250YWluZXIgPSBuZXcgQ29tcG9uZW50Q29udGFpbmVyKG5hbWUpO1xuICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBfY29tcG9uZW50cy52YWx1ZXMoKSkge1xuICAgIGNvbnRhaW5lci5hZGRDb21wb25lbnQoY29tcG9uZW50KTtcbiAgfVxuXG4gIGNvbnN0IG5ld0FwcCA9IG5ldyBGaXJlYmFzZUFwcEltcGwob3B0aW9ucywgY29uZmlnLCBjb250YWluZXIpO1xuXG4gIF9hcHBzLnNldChuYW1lLCBuZXdBcHApO1xuXG4gIHJldHVybiBuZXdBcHA7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbmQgaW5pdGlhbGl6ZXMgYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0gaW5zdGFuY2UuXG4gKlxuICogVGhlIGBGaXJlYmFzZVNlcnZlckFwcGAgaXMgc2ltaWxhciB0byBgRmlyZWJhc2VBcHBgLCBidXQgaXMgaW50ZW5kZWQgZm9yIGV4ZWN1dGlvbiBpblxuICogc2VydmVyIHNpZGUgcmVuZGVyaW5nIGVudmlyb25tZW50cyBvbmx5LiBJbml0aWFsaXphdGlvbiB3aWxsIGZhaWwgaWYgaW52b2tlZCBmcm9tIGFcbiAqIGJyb3dzZXIgZW52aXJvbm1lbnQuXG4gKlxuICogU2VlXG4gKiB7QGxpbmtcbiAqICAgaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3Mvd2ViL3NldHVwI2FkZF9maXJlYmFzZV90b195b3VyX2FwcFxuICogICB8IEFkZCBGaXJlYmFzZSB0byB5b3VyIGFwcH0gYW5kXG4gKiB7QGxpbmtcbiAqICAgaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3Mvd2ViL3NldHVwI211bHRpcGxlLXByb2plY3RzXG4gKiAgIHwgSW5pdGlhbGl6ZSBtdWx0aXBsZSBwcm9qZWN0c30gZm9yIGRldGFpbGVkIGRvY3VtZW50YXRpb24uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqXG4gKiAvLyBJbml0aWFsaXplIGFuIGluc3RhbmNlIG9mIGBGaXJlYmFzZVNlcnZlckFwcGAuXG4gKiAvLyBSZXRyaWV2ZSB5b3VyIG93biBvcHRpb25zIHZhbHVlcyBieSBhZGRpbmcgYSB3ZWIgYXBwIG9uXG4gKiAvLyBodHRwczovL2NvbnNvbGUuZmlyZWJhc2UuZ29vZ2xlLmNvbVxuICogaW5pdGlhbGl6ZVNlcnZlckFwcCh7XG4gKiAgICAgYXBpS2V5OiBcIkFJemEuLi4uXCIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdXRoIC8gR2VuZXJhbCBVc2VcbiAqICAgICBhdXRoRG9tYWluOiBcIllPVVJfQVBQLmZpcmViYXNlYXBwLmNvbVwiLCAgICAgICAgIC8vIEF1dGggd2l0aCBwb3B1cC9yZWRpcmVjdFxuICogICAgIGRhdGFiYXNlVVJMOiBcImh0dHBzOi8vWU9VUl9BUFAuZmlyZWJhc2Vpby5jb21cIiwgLy8gUmVhbHRpbWUgRGF0YWJhc2VcbiAqICAgICBzdG9yYWdlQnVja2V0OiBcIllPVVJfQVBQLmFwcHNwb3QuY29tXCIsICAgICAgICAgIC8vIFN0b3JhZ2VcbiAqICAgICBtZXNzYWdpbmdTZW5kZXJJZDogXCIxMjM0NTY3ODlcIiAgICAgICAgICAgICAgICAgIC8vIENsb3VkIE1lc3NhZ2luZ1xuICogICB9LFxuICogICB7XG4gKiAgICBhdXRoSWRUb2tlbjogXCJZb3VyIEF1dGggSUQgVG9rZW5cIlxuICogICB9KTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gYEZpcmViYXNlLkFwcE9wdGlvbnNgIHRvIGNvbmZpZ3VyZSB0aGUgYXBwJ3Mgc2VydmljZXMsIG9yIGFcbiAqICAgYSBgRmlyZWJhc2VBcHBgIGluc3RhbmNlIHdoaWNoIGNvbnRhaW5zIHRoZSBgQXBwT3B0aW9uc2Agd2l0aGluLlxuICogQHBhcmFtIGNvbmZpZyAtIE9wdGlvbmFsIGBGaXJlYmFzZVNlcnZlckFwcGAgc2V0dGluZ3MuXG4gKlxuICogQHJldHVybnMgVGhlIGluaXRpYWxpemVkIGBGaXJlYmFzZVNlcnZlckFwcGAuXG4gKlxuICogQHRocm93cyBJZiBpbnZva2VkIGluIGFuIHVuc3VwcG9ydGVkIG5vbi1zZXJ2ZXIgZW52aXJvbm1lbnQgc3VjaCBhcyBhIGJyb3dzZXIuXG4gKlxuICogQHRocm93cyBJZiB7QGxpbmsgRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncy5yZWxlYXNlT25EZXJlZn0gaXMgZGVmaW5lZCBidXQgdGhlIHJ1bnRpbWUgZG9lc24ndFxuICogICBwcm92aWRlIEZpbmFsaXphdGlvbiBSZWdpc3RyeSBzdXBwb3J0LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVTZXJ2ZXJBcHAoXG4gIG9wdGlvbnM6IEZpcmViYXNlT3B0aW9ucyB8IEZpcmViYXNlQXBwLFxuICBjb25maWc/OiBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzXG4pOiBGaXJlYmFzZVNlcnZlckFwcDtcblxuLyoqXG4gKiBDcmVhdGVzIGFuZCBpbml0aWFsaXplcyBhIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfSBpbnN0YW5jZS5cbiAqXG4gKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgYEZpcmViYXNlU2VydmVyQXBwYCBzZXR0aW5ncy5cbiAqXG4gKiBAcmV0dXJucyBUaGUgaW5pdGlhbGl6ZWQgYEZpcmViYXNlU2VydmVyQXBwYC5cbiAqXG4gKiBAdGhyb3dzIElmIGludm9rZWQgaW4gYW4gdW5zdXBwb3J0ZWQgbm9uLXNlcnZlciBlbnZpcm9ubWVudCBzdWNoIGFzIGEgYnJvd3Nlci5cbiAqIEB0aHJvd3MgSWYge0BsaW5rIEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MucmVsZWFzZU9uRGVyZWZ9IGlzIGRlZmluZWQgYnV0IHRoZSBydW50aW1lIGRvZXNuJ3RcbiAqICAgcHJvdmlkZSBGaW5hbGl6YXRpb24gUmVnaXN0cnkgc3VwcG9ydC5cbiAqIEB0aHJvd3MgSWYgdGhlIGBGSVJFQkFTRV9PUFRJT05TYCBlbnZpcm9ubWVudCB2YXJpYWJsZSBkb2VzIG5vdCBjb250YWluIGEgdmFsaWQgcHJvamVjdFxuICogICBjb25maWd1cmF0aW9uIHJlcXVpcmVkIGZvciBhdXRvLWluaXRpYWxpemF0aW9uLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVTZXJ2ZXJBcHAoXG4gIGNvbmZpZz86IEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3Ncbik6IEZpcmViYXNlU2VydmVyQXBwO1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVTZXJ2ZXJBcHAoXG4gIF9vcHRpb25zPzogRmlyZWJhc2VBcHAgfCBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzIHwgRmlyZWJhc2VPcHRpb25zLFxuICBfc2VydmVyQXBwQ29uZmlnOiBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzID0ge31cbik6IEZpcmViYXNlU2VydmVyQXBwIHtcbiAgaWYgKGlzQnJvd3NlcigpICYmICFpc1dlYldvcmtlcigpKSB7XG4gICAgLy8gRmlyZWJhc2VTZXJ2ZXJBcHAgaXNuJ3QgZGVzaWduZWQgdG8gYmUgcnVuIGluIGJyb3dzZXJzLlxuICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLklOVkFMSURfU0VSVkVSX0FQUF9FTlZJUk9OTUVOVCk7XG4gIH1cblxuICBsZXQgZmlyZWJhc2VPcHRpb25zOiBGaXJlYmFzZU9wdGlvbnMgfCB1bmRlZmluZWQ7XG4gIGxldCBzZXJ2ZXJBcHBTZXR0aW5nczogRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncyA9IF9zZXJ2ZXJBcHBDb25maWcgfHwge307XG5cbiAgaWYgKF9vcHRpb25zKSB7XG4gICAgaWYgKF9pc0ZpcmViYXNlQXBwKF9vcHRpb25zKSkge1xuICAgICAgZmlyZWJhc2VPcHRpb25zID0gX29wdGlvbnMub3B0aW9ucztcbiAgICB9IGVsc2UgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MoX29wdGlvbnMpKSB7XG4gICAgICBzZXJ2ZXJBcHBTZXR0aW5ncyA9IF9vcHRpb25zO1xuICAgIH0gZWxzZSB7XG4gICAgICBmaXJlYmFzZU9wdGlvbnMgPSBfb3B0aW9ucztcbiAgICB9XG4gIH1cblxuICBpZiAoc2VydmVyQXBwU2V0dGluZ3MuYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkID09PSB1bmRlZmluZWQpIHtcbiAgICBzZXJ2ZXJBcHBTZXR0aW5ncy5hdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQgPSB0cnVlO1xuICB9XG5cbiAgZmlyZWJhc2VPcHRpb25zIHx8PSBnZXREZWZhdWx0QXBwQ29uZmlnKCk7XG4gIGlmICghZmlyZWJhc2VPcHRpb25zKSB7XG4gICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuTk9fT1BUSU9OUyk7XG4gIH1cblxuICAvLyBCdWlsZCBhbiBhcHAgbmFtZSBiYXNlZCBvbiBhIGhhc2ggb2YgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucy5cbiAgY29uc3QgbmFtZU9iaiA9IHtcbiAgICAuLi5zZXJ2ZXJBcHBTZXR0aW5ncyxcbiAgICAuLi5maXJlYmFzZU9wdGlvbnNcbiAgfTtcblxuICAvLyBIb3dldmVyLCBEbyBub3QgbWFuZ2xlIHRoZSBuYW1lIGJhc2VkIG9uIHJlbGVhc2VPbkRlcmVmLCBzaW5jZSBpdCB3aWxsIHZhcnkgYmV0d2VlbiB0aGVcbiAgLy8gY29uc3RydWN0aW9uIG9mIEZpcmViYXNlU2VydmVyQXBwIGluc3RhbmNlcy4gRm9yIGV4YW1wbGUsIGlmIHRoZSBvYmplY3QgaXMgdGhlIHJlcXVlc3QgaGVhZGVycy5cbiAgaWYgKG5hbWVPYmoucmVsZWFzZU9uRGVyZWYgIT09IHVuZGVmaW5lZCkge1xuICAgIGRlbGV0ZSBuYW1lT2JqLnJlbGVhc2VPbkRlcmVmO1xuICB9XG5cbiAgY29uc3QgaGFzaENvZGUgPSAoczogc3RyaW5nKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gWy4uLnNdLnJlZHVjZShcbiAgICAgIChoYXNoLCBjKSA9PiAoTWF0aC5pbXVsKDMxLCBoYXNoKSArIGMuY2hhckNvZGVBdCgwKSkgfCAwLFxuICAgICAgMFxuICAgICk7XG4gIH07XG5cbiAgaWYgKHNlcnZlckFwcFNldHRpbmdzLnJlbGVhc2VPbkRlcmVmICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAodHlwZW9mIEZpbmFsaXphdGlvblJlZ2lzdHJ5ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoXG4gICAgICAgIEFwcEVycm9yLkZJTkFMSVpBVElPTl9SRUdJU1RSWV9OT1RfU1VQUE9SVEVELFxuICAgICAgICB7fVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBuYW1lU3RyaW5nID0gJycgKyBoYXNoQ29kZShKU09OLnN0cmluZ2lmeShuYW1lT2JqKSk7XG4gIGNvbnN0IGV4aXN0aW5nQXBwID0gX3NlcnZlckFwcHMuZ2V0KG5hbWVTdHJpbmcpIGFzIEZpcmViYXNlU2VydmVyQXBwO1xuICBpZiAoZXhpc3RpbmdBcHApIHtcbiAgICAoZXhpc3RpbmdBcHAgYXMgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsKS5pbmNSZWZDb3VudChcbiAgICAgIHNlcnZlckFwcFNldHRpbmdzLnJlbGVhc2VPbkRlcmVmXG4gICAgKTtcbiAgICByZXR1cm4gZXhpc3RpbmdBcHA7XG4gIH1cblxuICBjb25zdCBjb250YWluZXIgPSBuZXcgQ29tcG9uZW50Q29udGFpbmVyKG5hbWVTdHJpbmcpO1xuICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBfY29tcG9uZW50cy52YWx1ZXMoKSkge1xuICAgIGNvbnRhaW5lci5hZGRDb21wb25lbnQoY29tcG9uZW50KTtcbiAgfVxuXG4gIGNvbnN0IG5ld0FwcCA9IG5ldyBGaXJlYmFzZVNlcnZlckFwcEltcGwoXG4gICAgZmlyZWJhc2VPcHRpb25zLFxuICAgIHNlcnZlckFwcFNldHRpbmdzLFxuICAgIG5hbWVTdHJpbmcsXG4gICAgY29udGFpbmVyXG4gICk7XG5cbiAgX3NlcnZlckFwcHMuc2V0KG5hbWVTdHJpbmcsIG5ld0FwcCk7XG5cbiAgcmV0dXJuIG5ld0FwcDtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZUFwcH0gaW5zdGFuY2UuXG4gKlxuICogV2hlbiBjYWxsZWQgd2l0aCBubyBhcmd1bWVudHMsIHRoZSBkZWZhdWx0IGFwcCBpcyByZXR1cm5lZC4gV2hlbiBhbiBhcHAgbmFtZVxuICogaXMgcHJvdmlkZWQsIHRoZSBhcHAgY29ycmVzcG9uZGluZyB0byB0aGF0IG5hbWUgaXMgcmV0dXJuZWQuXG4gKlxuICogQW4gZXhjZXB0aW9uIGlzIHRocm93biBpZiB0aGUgYXBwIGJlaW5nIHJldHJpZXZlZCBoYXMgbm90IHlldCBiZWVuXG4gKiBpbml0aWFsaXplZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gUmV0dXJuIHRoZSBkZWZhdWx0IGFwcFxuICogY29uc3QgYXBwID0gZ2V0QXBwKCk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gUmV0dXJuIGEgbmFtZWQgYXBwXG4gKiBjb25zdCBvdGhlckFwcCA9IGdldEFwcChcIm90aGVyQXBwXCIpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIG5hbWUgLSBPcHRpb25hbCBuYW1lIG9mIHRoZSBhcHAgdG8gcmV0dXJuLiBJZiBubyBuYW1lIGlzXG4gKiAgIHByb3ZpZGVkLCB0aGUgZGVmYXVsdCBpcyBgXCJbREVGQVVMVF1cImAuXG4gKlxuICogQHJldHVybnMgVGhlIGFwcCBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm92aWRlZCBhcHAgbmFtZS5cbiAqICAgSWYgbm8gYXBwIG5hbWUgaXMgcHJvdmlkZWQsIHRoZSBkZWZhdWx0IGFwcCBpcyByZXR1cm5lZC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBcHAobmFtZTogc3RyaW5nID0gREVGQVVMVF9FTlRSWV9OQU1FKTogRmlyZWJhc2VBcHAge1xuICBjb25zdCBhcHAgPSBfYXBwcy5nZXQobmFtZSk7XG4gIGlmICghYXBwICYmIG5hbWUgPT09IERFRkFVTFRfRU5UUllfTkFNRSAmJiBnZXREZWZhdWx0QXBwQ29uZmlnKCkpIHtcbiAgICByZXR1cm4gaW5pdGlhbGl6ZUFwcCgpO1xuICB9XG4gIGlmICghYXBwKSB7XG4gICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuTk9fQVBQLCB7IGFwcE5hbWU6IG5hbWUgfSk7XG4gIH1cblxuICByZXR1cm4gYXBwO1xufVxuXG4vKipcbiAqIEEgKHJlYWQtb25seSkgYXJyYXkgb2YgYWxsIGluaXRpYWxpemVkIGFwcHMuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBcHBzKCk6IEZpcmViYXNlQXBwW10ge1xuICByZXR1cm4gQXJyYXkuZnJvbShfYXBwcy52YWx1ZXMoKSk7XG59XG5cbi8qKlxuICogUmVuZGVycyB0aGlzIGFwcCB1bnVzYWJsZSBhbmQgZnJlZXMgdGhlIHJlc291cmNlcyBvZiBhbGwgYXNzb2NpYXRlZFxuICogc2VydmljZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGRlbGV0ZUFwcChhcHApXG4gKiAgIC50aGVuKGZ1bmN0aW9uKCkge1xuICogICAgIGNvbnNvbGUubG9nKFwiQXBwIGRlbGV0ZWQgc3VjY2Vzc2Z1bGx5XCIpO1xuICogICB9KVxuICogICAuY2F0Y2goZnVuY3Rpb24oZXJyb3IpIHtcbiAqICAgICBjb25zb2xlLmxvZyhcIkVycm9yIGRlbGV0aW5nIGFwcDpcIiwgZXJyb3IpO1xuICogICB9KTtcbiAqIGBgYFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZUFwcChhcHA6IEZpcmViYXNlQXBwKTogUHJvbWlzZTx2b2lkPiB7XG4gIGxldCBjbGVhbnVwUHJvdmlkZXJzID0gZmFsc2U7XG4gIGNvbnN0IG5hbWUgPSBhcHAubmFtZTtcbiAgaWYgKF9hcHBzLmhhcyhuYW1lKSkge1xuICAgIGNsZWFudXBQcm92aWRlcnMgPSB0cnVlO1xuICAgIF9hcHBzLmRlbGV0ZShuYW1lKTtcbiAgfSBlbHNlIGlmIChfc2VydmVyQXBwcy5oYXMobmFtZSkpIHtcbiAgICBjb25zdCBmaXJlYmFzZVNlcnZlckFwcCA9IGFwcCBhcyBGaXJlYmFzZVNlcnZlckFwcEltcGw7XG4gICAgaWYgKGZpcmViYXNlU2VydmVyQXBwLmRlY1JlZkNvdW50KCkgPD0gMCkge1xuICAgICAgX3NlcnZlckFwcHMuZGVsZXRlKG5hbWUpO1xuICAgICAgY2xlYW51cFByb3ZpZGVycyA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNsZWFudXBQcm92aWRlcnMpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsKS5jb250YWluZXJcbiAgICAgICAgLmdldFByb3ZpZGVycygpXG4gICAgICAgIC5tYXAocHJvdmlkZXIgPT4gcHJvdmlkZXIuZGVsZXRlKCkpXG4gICAgKTtcbiAgICAoYXBwIGFzIEZpcmViYXNlQXBwSW1wbCkuaXNEZWxldGVkID0gdHJ1ZTtcbiAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGxpYnJhcnkncyBuYW1lIGFuZCB2ZXJzaW9uIGZvciBwbGF0Zm9ybSBsb2dnaW5nIHB1cnBvc2VzLlxuICogQHBhcmFtIGxpYnJhcnkgLSBOYW1lIG9mIDFwIG9yIDNwIGxpYnJhcnkgKGUuZy4gZmlyZXN0b3JlLCBhbmd1bGFyZmlyZSlcbiAqIEBwYXJhbSB2ZXJzaW9uIC0gQ3VycmVudCB2ZXJzaW9uIG9mIHRoYXQgbGlicmFyeS5cbiAqIEBwYXJhbSB2YXJpYW50IC0gQnVuZGxlIHZhcmlhbnQsIGUuZy4sIG5vZGUsIHJuLCBldGMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJWZXJzaW9uKFxuICBsaWJyYXJ5S2V5T3JOYW1lOiBzdHJpbmcsXG4gIHZlcnNpb246IHN0cmluZyxcbiAgdmFyaWFudD86IHN0cmluZ1xuKTogdm9pZCB7XG4gIC8vIFRPRE86IFdlIGNhbiB1c2UgdGhpcyBjaGVjayB0byB3aGl0ZWxpc3Qgc3RyaW5ncyB3aGVuL2lmIHdlIHNldCB1cFxuICAvLyBhIGdvb2Qgd2hpdGVsaXN0IHN5c3RlbS5cbiAgbGV0IGxpYnJhcnkgPSBQTEFURk9STV9MT0dfU1RSSU5HW2xpYnJhcnlLZXlPck5hbWVdID8/IGxpYnJhcnlLZXlPck5hbWU7XG4gIGlmICh2YXJpYW50KSB7XG4gICAgbGlicmFyeSArPSBgLSR7dmFyaWFudH1gO1xuICB9XG4gIGNvbnN0IGxpYnJhcnlNaXNtYXRjaCA9IGxpYnJhcnkubWF0Y2goL1xcc3xcXC8vKTtcbiAgY29uc3QgdmVyc2lvbk1pc21hdGNoID0gdmVyc2lvbi5tYXRjaCgvXFxzfFxcLy8pO1xuICBpZiAobGlicmFyeU1pc21hdGNoIHx8IHZlcnNpb25NaXNtYXRjaCkge1xuICAgIGNvbnN0IHdhcm5pbmcgPSBbXG4gICAgICBgVW5hYmxlIHRvIHJlZ2lzdGVyIGxpYnJhcnkgXCIke2xpYnJhcnl9XCIgd2l0aCB2ZXJzaW9uIFwiJHt2ZXJzaW9ufVwiOmBcbiAgICBdO1xuICAgIGlmIChsaWJyYXJ5TWlzbWF0Y2gpIHtcbiAgICAgIHdhcm5pbmcucHVzaChcbiAgICAgICAgYGxpYnJhcnkgbmFtZSBcIiR7bGlicmFyeX1cIiBjb250YWlucyBpbGxlZ2FsIGNoYXJhY3RlcnMgKHdoaXRlc3BhY2Ugb3IgXCIvXCIpYFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKGxpYnJhcnlNaXNtYXRjaCAmJiB2ZXJzaW9uTWlzbWF0Y2gpIHtcbiAgICAgIHdhcm5pbmcucHVzaCgnYW5kJyk7XG4gICAgfVxuICAgIGlmICh2ZXJzaW9uTWlzbWF0Y2gpIHtcbiAgICAgIHdhcm5pbmcucHVzaChcbiAgICAgICAgYHZlcnNpb24gbmFtZSBcIiR7dmVyc2lvbn1cIiBjb250YWlucyBpbGxlZ2FsIGNoYXJhY3RlcnMgKHdoaXRlc3BhY2Ugb3IgXCIvXCIpYFxuICAgICAgKTtcbiAgICB9XG4gICAgbG9nZ2VyLndhcm4od2FybmluZy5qb2luKCcgJykpO1xuICAgIHJldHVybjtcbiAgfVxuICBfcmVnaXN0ZXJDb21wb25lbnQoXG4gICAgbmV3IENvbXBvbmVudChcbiAgICAgIGAke2xpYnJhcnl9LXZlcnNpb25gIGFzIE5hbWUsXG4gICAgICAoKSA9PiAoeyBsaWJyYXJ5LCB2ZXJzaW9uIH0pLFxuICAgICAgQ29tcG9uZW50VHlwZS5WRVJTSU9OXG4gICAgKVxuICApO1xufVxuXG4vKipcbiAqIFNldHMgbG9nIGhhbmRsZXIgZm9yIGFsbCBGaXJlYmFzZSBTREtzLlxuICogQHBhcmFtIGxvZ0NhbGxiYWNrIC0gQW4gb3B0aW9uYWwgY3VzdG9tIGxvZyBoYW5kbGVyIHRoYXQgZXhlY3V0ZXMgdXNlciBjb2RlIHdoZW5ldmVyXG4gKiB0aGUgRmlyZWJhc2UgU0RLIG1ha2VzIGEgbG9nZ2luZyBjYWxsLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uTG9nKFxuICBsb2dDYWxsYmFjazogTG9nQ2FsbGJhY2sgfCBudWxsLFxuICBvcHRpb25zPzogTG9nT3B0aW9uc1xuKTogdm9pZCB7XG4gIGlmIChsb2dDYWxsYmFjayAhPT0gbnVsbCAmJiB0eXBlb2YgbG9nQ2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5JTlZBTElEX0xPR19BUkdVTUVOVCk7XG4gIH1cbiAgc2V0VXNlckxvZ0hhbmRsZXIobG9nQ2FsbGJhY2ssIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIFNldHMgbG9nIGxldmVsIGZvciBhbGwgRmlyZWJhc2UgU0RLcy5cbiAqXG4gKiBBbGwgb2YgdGhlIGxvZyB0eXBlcyBhYm92ZSB0aGUgY3VycmVudCBsb2cgbGV2ZWwgYXJlIGNhcHR1cmVkIChpLmUuIGlmXG4gKiB5b3Ugc2V0IHRoZSBsb2cgbGV2ZWwgdG8gYGluZm9gLCBlcnJvcnMgYXJlIGxvZ2dlZCwgYnV0IGBkZWJ1Z2AgYW5kXG4gKiBgdmVyYm9zZWAgbG9ncyBhcmUgbm90KS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRMb2dMZXZlbChsb2dMZXZlbDogTG9nTGV2ZWxTdHJpbmcpOiB2b2lkIHtcbiAgc2V0TG9nTGV2ZWxJbXBsKGxvZ0xldmVsKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgREJTY2hlbWEsIG9wZW5EQiwgSURCUERhdGFiYXNlIH0gZnJvbSAnaWRiJztcbmltcG9ydCB7IEFwcEVycm9yLCBFUlJPUl9GQUNUT1JZIH0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHsgRmlyZWJhc2VBcHAgfSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBIZWFydGJlYXRzSW5JbmRleGVkREIgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcblxuY29uc3QgREJfTkFNRSA9ICdmaXJlYmFzZS1oZWFydGJlYXQtZGF0YWJhc2UnO1xuY29uc3QgREJfVkVSU0lPTiA9IDE7XG5jb25zdCBTVE9SRV9OQU1FID0gJ2ZpcmViYXNlLWhlYXJ0YmVhdC1zdG9yZSc7XG5cbmludGVyZmFjZSBBcHBEQiBleHRlbmRzIERCU2NoZW1hIHtcbiAgJ2ZpcmViYXNlLWhlYXJ0YmVhdC1zdG9yZSc6IHtcbiAgICBrZXk6IHN0cmluZztcbiAgICB2YWx1ZTogSGVhcnRiZWF0c0luSW5kZXhlZERCO1xuICB9O1xufVxuXG5sZXQgZGJQcm9taXNlOiBQcm9taXNlPElEQlBEYXRhYmFzZTxBcHBEQj4+IHwgbnVsbCA9IG51bGw7XG5mdW5jdGlvbiBnZXREYlByb21pc2UoKTogUHJvbWlzZTxJREJQRGF0YWJhc2U8QXBwREI+PiB7XG4gIGlmICghZGJQcm9taXNlKSB7XG4gICAgZGJQcm9taXNlID0gb3BlbkRCPEFwcERCPihEQl9OQU1FLCBEQl9WRVJTSU9OLCB7XG4gICAgICB1cGdyYWRlOiAoZGIsIG9sZFZlcnNpb24pID0+IHtcbiAgICAgICAgLy8gV2UgZG9uJ3QgdXNlICdicmVhaycgaW4gdGhpcyBzd2l0Y2ggc3RhdGVtZW50LCB0aGUgZmFsbC10aHJvdWdoXG4gICAgICAgIC8vIGJlaGF2aW9yIGlzIHdoYXQgd2Ugd2FudCwgYmVjYXVzZSBpZiB0aGVyZSBhcmUgbXVsdGlwbGUgdmVyc2lvbnMgYmV0d2VlblxuICAgICAgICAvLyB0aGUgb2xkIHZlcnNpb24gYW5kIHRoZSBjdXJyZW50IHZlcnNpb24sIHdlIHdhbnQgQUxMIHRoZSBtaWdyYXRpb25zXG4gICAgICAgIC8vIHRoYXQgY29ycmVzcG9uZCB0byB0aG9zZSB2ZXJzaW9ucyB0byBydW4sIG5vdCBvbmx5IHRoZSBsYXN0IG9uZS5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlZmF1bHQtY2FzZVxuICAgICAgICBzd2l0Y2ggKG9sZFZlcnNpb24pIHtcbiAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShTVE9SRV9OQU1FKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgLy8gU2FmYXJpL2lPUyBicm93c2VycyB0aHJvdyBvY2Nhc2lvbmFsIGV4Y2VwdGlvbnMgb25cbiAgICAgICAgICAgICAgLy8gZGIuY3JlYXRlT2JqZWN0U3RvcmUoKSB0aGF0IG1heSBiZSBhIGJ1Zy4gQXZvaWQgYmxvY2tpbmdcbiAgICAgICAgICAgICAgLy8gdGhlIHJlc3Qgb2YgdGhlIGFwcCBmdW5jdGlvbmFsaXR5LlxuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KS5jYXRjaChlID0+IHtcbiAgICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLklEQl9PUEVOLCB7XG4gICAgICAgIG9yaWdpbmFsRXJyb3JNZXNzYWdlOiBlLm1lc3NhZ2VcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiBkYlByb21pc2U7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkSGVhcnRiZWF0c0Zyb21JbmRleGVkREIoXG4gIGFwcDogRmlyZWJhc2VBcHBcbik6IFByb21pc2U8SGVhcnRiZWF0c0luSW5kZXhlZERCIHwgdW5kZWZpbmVkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgZGIgPSBhd2FpdCBnZXREYlByb21pc2UoKTtcbiAgICBjb25zdCB0eCA9IGRiLnRyYW5zYWN0aW9uKFNUT1JFX05BTUUpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHR4Lm9iamVjdFN0b3JlKFNUT1JFX05BTUUpLmdldChjb21wdXRlS2V5KGFwcCkpO1xuICAgIC8vIFdlIGFscmVhZHkgaGF2ZSB0aGUgdmFsdWUgYnV0IHR4LmRvbmUgY2FuIHRocm93LFxuICAgIC8vIHNvIHdlIG5lZWQgdG8gYXdhaXQgaXQgaGVyZSB0byBjYXRjaCBlcnJvcnNcbiAgICBhd2FpdCB0eC5kb25lO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIEZpcmViYXNlRXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKGUubWVzc2FnZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlkYkdldEVycm9yID0gRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuSURCX0dFVCwge1xuICAgICAgICBvcmlnaW5hbEVycm9yTWVzc2FnZTogKGUgYXMgRXJyb3IpPy5tZXNzYWdlXG4gICAgICB9KTtcbiAgICAgIGxvZ2dlci53YXJuKGlkYkdldEVycm9yLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVIZWFydGJlYXRzVG9JbmRleGVkREIoXG4gIGFwcDogRmlyZWJhc2VBcHAsXG4gIGhlYXJ0YmVhdE9iamVjdDogSGVhcnRiZWF0c0luSW5kZXhlZERCXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBkYiA9IGF3YWl0IGdldERiUHJvbWlzZSgpO1xuICAgIGNvbnN0IHR4ID0gZGIudHJhbnNhY3Rpb24oU1RPUkVfTkFNRSwgJ3JlYWR3cml0ZScpO1xuICAgIGNvbnN0IG9iamVjdFN0b3JlID0gdHgub2JqZWN0U3RvcmUoU1RPUkVfTkFNRSk7XG4gICAgYXdhaXQgb2JqZWN0U3RvcmUucHV0KGhlYXJ0YmVhdE9iamVjdCwgY29tcHV0ZUtleShhcHApKTtcbiAgICBhd2FpdCB0eC5kb25lO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBGaXJlYmFzZUVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihlLm1lc3NhZ2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBpZGJHZXRFcnJvciA9IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLklEQl9XUklURSwge1xuICAgICAgICBvcmlnaW5hbEVycm9yTWVzc2FnZTogKGUgYXMgRXJyb3IpPy5tZXNzYWdlXG4gICAgICB9KTtcbiAgICAgIGxvZ2dlci53YXJuKGlkYkdldEVycm9yLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjb21wdXRlS2V5KGFwcDogRmlyZWJhc2VBcHApOiBzdHJpbmcge1xuICByZXR1cm4gYCR7YXBwLm5hbWV9ISR7YXBwLm9wdGlvbnMuYXBwSWR9YDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnRDb250YWluZXIgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7XG4gIGJhc2U2NHVybEVuY29kZVdpdGhvdXRQYWRkaW5nLFxuICBpc0luZGV4ZWREQkF2YWlsYWJsZSxcbiAgdmFsaWRhdGVJbmRleGVkREJPcGVuYWJsZVxufSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQge1xuICByZWFkSGVhcnRiZWF0c0Zyb21JbmRleGVkREIsXG4gIHdyaXRlSGVhcnRiZWF0c1RvSW5kZXhlZERCXG59IGZyb20gJy4vaW5kZXhlZGRiJztcbmltcG9ydCB7IEZpcmViYXNlQXBwIH0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHtcbiAgSGVhcnRiZWF0c0J5VXNlckFnZW50LFxuICBIZWFydGJlYXRTZXJ2aWNlLFxuICBIZWFydGJlYXRzSW5JbmRleGVkREIsXG4gIEhlYXJ0YmVhdFN0b3JhZ2UsXG4gIFNpbmdsZURhdGVIZWFydGJlYXRcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dlcic7XG5cbmNvbnN0IE1BWF9IRUFERVJfQllURVMgPSAxMDI0O1xuZXhwb3J0IGNvbnN0IE1BWF9OVU1fU1RPUkVEX0hFQVJUQkVBVFMgPSAzMDtcblxuZXhwb3J0IGNsYXNzIEhlYXJ0YmVhdFNlcnZpY2VJbXBsIGltcGxlbWVudHMgSGVhcnRiZWF0U2VydmljZSB7XG4gIC8qKlxuICAgKiBUaGUgcGVyc2lzdGVuY2UgbGF5ZXIgZm9yIGhlYXJ0YmVhdHNcbiAgICogTGVhdmUgcHVibGljIGZvciBlYXNpZXIgdGVzdGluZy5cbiAgICovXG4gIF9zdG9yYWdlOiBIZWFydGJlYXRTdG9yYWdlSW1wbDtcblxuICAvKipcbiAgICogSW4tbWVtb3J5IGNhY2hlIGZvciBoZWFydGJlYXRzLCB1c2VkIGJ5IGdldEhlYXJ0YmVhdHNIZWFkZXIoKSB0byBnZW5lcmF0ZVxuICAgKiB0aGUgaGVhZGVyIHN0cmluZy5cbiAgICogU3RvcmVzIG9uZSByZWNvcmQgcGVyIGRhdGUuIFRoaXMgd2lsbCBiZSBjb25zb2xpZGF0ZWQgaW50byB0aGUgc3RhbmRhcmRcbiAgICogZm9ybWF0IG9mIG9uZSByZWNvcmQgcGVyIHVzZXIgYWdlbnQgc3RyaW5nIGJlZm9yZSBiZWluZyBzZW50IGFzIGEgaGVhZGVyLlxuICAgKiBQb3B1bGF0ZWQgZnJvbSBpbmRleGVkREIgd2hlbiB0aGUgY29udHJvbGxlciBpcyBpbnN0YW50aWF0ZWQgYW5kIHNob3VsZFxuICAgKiBiZSBrZXB0IGluIHN5bmMgd2l0aCBpbmRleGVkREIuXG4gICAqIExlYXZlIHB1YmxpYyBmb3IgZWFzaWVyIHRlc3RpbmcuXG4gICAqL1xuICBfaGVhcnRiZWF0c0NhY2hlOiBIZWFydGJlYXRzSW5JbmRleGVkREIgfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogdGhlIGluaXRpYWxpemF0aW9uIHByb21pc2UgZm9yIHBvcHVsYXRpbmcgaGVhcnRiZWF0Q2FjaGUuXG4gICAqIElmIGdldEhlYXJ0YmVhdHNIZWFkZXIoKSBpcyBjYWxsZWQgYmVmb3JlIHRoZSBwcm9taXNlIHJlc29sdmVzXG4gICAqIChoZWFydGJlYXRzQ2FjaGUgPT0gbnVsbCksIGl0IHNob3VsZCB3YWl0IGZvciB0aGlzIHByb21pc2VcbiAgICogTGVhdmUgcHVibGljIGZvciBlYXNpZXIgdGVzdGluZy5cbiAgICovXG4gIF9oZWFydGJlYXRzQ2FjaGVQcm9taXNlOiBQcm9taXNlPEhlYXJ0YmVhdHNJbkluZGV4ZWREQj47XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY29udGFpbmVyOiBDb21wb25lbnRDb250YWluZXIpIHtcbiAgICBjb25zdCBhcHAgPSB0aGlzLmNvbnRhaW5lci5nZXRQcm92aWRlcignYXBwJykuZ2V0SW1tZWRpYXRlKCk7XG4gICAgdGhpcy5fc3RvcmFnZSA9IG5ldyBIZWFydGJlYXRTdG9yYWdlSW1wbChhcHApO1xuICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZVByb21pc2UgPSB0aGlzLl9zdG9yYWdlLnJlYWQoKS50aGVuKHJlc3VsdCA9PiB7XG4gICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUgPSByZXN1bHQ7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB0byByZXBvcnQgYSBoZWFydGJlYXQuIFRoZSBmdW5jdGlvbiB3aWxsIGdlbmVyYXRlXG4gICAqIGEgSGVhcnRiZWF0c0J5VXNlckFnZW50IG9iamVjdCwgdXBkYXRlIGhlYXJ0YmVhdHNDYWNoZSwgYW5kIHBlcnNpc3QgaXRcbiAgICogdG8gSW5kZXhlZERCLlxuICAgKiBOb3RlIHRoYXQgd2Ugb25seSBzdG9yZSBvbmUgaGVhcnRiZWF0IHBlciBkYXkuIFNvIGlmIGEgaGVhcnRiZWF0IGZvciB0b2RheSBpc1xuICAgKiBhbHJlYWR5IGxvZ2dlZCwgc3Vic2VxdWVudCBjYWxscyB0byB0aGlzIGZ1bmN0aW9uIGluIHRoZSBzYW1lIGRheSB3aWxsIGJlIGlnbm9yZWQuXG4gICAqL1xuICBhc3luYyB0cmlnZ2VySGVhcnRiZWF0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwbGF0Zm9ybUxvZ2dlciA9IHRoaXMuY29udGFpbmVyXG4gICAgICAgIC5nZXRQcm92aWRlcigncGxhdGZvcm0tbG9nZ2VyJylcbiAgICAgICAgLmdldEltbWVkaWF0ZSgpO1xuXG4gICAgICAvLyBUaGlzIGlzIHRoZSBcIkZpcmViYXNlIHVzZXIgYWdlbnRcIiBzdHJpbmcgZnJvbSB0aGUgcGxhdGZvcm0gbG9nZ2VyXG4gICAgICAvLyBzZXJ2aWNlLCBub3QgdGhlIGJyb3dzZXIgdXNlciBhZ2VudC5cbiAgICAgIGNvbnN0IGFnZW50ID0gcGxhdGZvcm1Mb2dnZXIuZ2V0UGxhdGZvcm1JbmZvU3RyaW5nKCk7XG4gICAgICBjb25zdCBkYXRlID0gZ2V0VVRDRGF0ZVN0cmluZygpO1xuICAgICAgaWYgKHRoaXMuX2hlYXJ0YmVhdHNDYWNoZT8uaGVhcnRiZWF0cyA9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZSA9IGF3YWl0IHRoaXMuX2hlYXJ0YmVhdHNDYWNoZVByb21pc2U7XG4gICAgICAgIC8vIElmIHdlIGZhaWxlZCB0byBjb25zdHJ1Y3QgYSBoZWFydGJlYXRzIGNhY2hlLCB0aGVuIHJldHVybiBpbW1lZGlhdGVseS5cbiAgICAgICAgaWYgKHRoaXMuX2hlYXJ0YmVhdHNDYWNoZT8uaGVhcnRiZWF0cyA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBEbyBub3Qgc3RvcmUgYSBoZWFydGJlYXQgaWYgb25lIGlzIGFscmVhZHkgc3RvcmVkIGZvciB0aGlzIGRheVxuICAgICAgLy8gb3IgaWYgYSBoZWFkZXIgaGFzIGFscmVhZHkgYmVlbiBzZW50IHRvZGF5LlxuICAgICAgaWYgKFxuICAgICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUubGFzdFNlbnRIZWFydGJlYXREYXRlID09PSBkYXRlIHx8XG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzLnNvbWUoXG4gICAgICAgICAgc2luZ2xlRGF0ZUhlYXJ0YmVhdCA9PiBzaW5nbGVEYXRlSGVhcnRiZWF0LmRhdGUgPT09IGRhdGVcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRoZXJlIGlzIG5vIGVudHJ5IGZvciB0aGlzIGRhdGUuIENyZWF0ZSBvbmUuXG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzLnB1c2goeyBkYXRlLCBhZ2VudCB9KTtcblxuICAgICAgICAvLyBJZiB0aGUgbnVtYmVyIG9mIHN0b3JlZCBoZWFydGJlYXRzIGV4Y2VlZHMgdGhlIG1heGltdW0gbnVtYmVyIG9mIHN0b3JlZCBoZWFydGJlYXRzLCByZW1vdmUgdGhlIGhlYXJ0YmVhdCB3aXRoIHRoZSBlYXJsaWVzdCBkYXRlLlxuICAgICAgICAvLyBTaW5jZSB0aGlzIGlzIGV4ZWN1dGVkIGVhY2ggdGltZSBhIGhlYXJ0YmVhdCBpcyBwdXNoZWQsIHRoZSBsaW1pdCBjYW4gb25seSBiZSBleGNlZWRlZCBieSBvbmUsIHNvIG9ubHkgb25lIG5lZWRzIHRvIGJlIHJlbW92ZWQuXG4gICAgICAgIGlmIChcbiAgICAgICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUuaGVhcnRiZWF0cy5sZW5ndGggPiBNQVhfTlVNX1NUT1JFRF9IRUFSVEJFQVRTXG4gICAgICAgICkge1xuICAgICAgICAgIGNvbnN0IGVhcmxpZXN0SGVhcnRiZWF0SWR4ID0gZ2V0RWFybGllc3RIZWFydGJlYXRJZHgoXG4gICAgICAgICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUuaGVhcnRiZWF0c1xuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmhlYXJ0YmVhdHMuc3BsaWNlKGVhcmxpZXN0SGVhcnRiZWF0SWR4LCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5fc3RvcmFnZS5vdmVyd3JpdGUodGhpcy5faGVhcnRiZWF0c0NhY2hlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dnZXIud2FybihlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZyB3aGljaCBjYW4gYmUgYXR0YWNoZWQgdG8gdGhlIGhlYXJ0YmVhdC1zcGVjaWZpYyBoZWFkZXIgZGlyZWN0bHkuXG4gICAqIEl0IGFsc28gY2xlYXJzIGFsbCBoZWFydGJlYXRzIGZyb20gbWVtb3J5IGFzIHdlbGwgYXMgaW4gSW5kZXhlZERCLlxuICAgKlxuICAgKiBOT1RFOiBDb25zdW1pbmcgcHJvZHVjdCBTREtzIHNob3VsZCBub3Qgc2VuZCB0aGUgaGVhZGVyIGlmIHRoaXMgbWV0aG9kXG4gICAqIHJldHVybnMgYW4gZW1wdHkgc3RyaW5nLlxuICAgKi9cbiAgYXN5bmMgZ2V0SGVhcnRiZWF0c0hlYWRlcigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5faGVhcnRiZWF0c0NhY2hlID09PSBudWxsKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2hlYXJ0YmVhdHNDYWNoZVByb21pc2U7XG4gICAgICB9XG4gICAgICAvLyBJZiBpdCdzIHN0aWxsIG51bGwgb3IgdGhlIGFycmF5IGlzIGVtcHR5LCB0aGVyZSBpcyBubyBkYXRhIHRvIHNlbmQuXG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZT8uaGVhcnRiZWF0cyA9PSBudWxsIHx8XG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzLmxlbmd0aCA9PT0gMFxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRhdGUgPSBnZXRVVENEYXRlU3RyaW5nKCk7XG4gICAgICAvLyBFeHRyYWN0IGFzIG1hbnkgaGVhcnRiZWF0cyBmcm9tIHRoZSBjYWNoZSBhcyB3aWxsIGZpdCB1bmRlciB0aGUgc2l6ZSBsaW1pdC5cbiAgICAgIGNvbnN0IHsgaGVhcnRiZWF0c1RvU2VuZCwgdW5zZW50RW50cmllcyB9ID0gZXh0cmFjdEhlYXJ0YmVhdHNGb3JIZWFkZXIoXG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzXG4gICAgICApO1xuICAgICAgY29uc3QgaGVhZGVyU3RyaW5nID0gYmFzZTY0dXJsRW5jb2RlV2l0aG91dFBhZGRpbmcoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHsgdmVyc2lvbjogMiwgaGVhcnRiZWF0czogaGVhcnRiZWF0c1RvU2VuZCB9KVxuICAgICAgKTtcbiAgICAgIC8vIFN0b3JlIGxhc3Qgc2VudCBkYXRlIHRvIHByZXZlbnQgYW5vdGhlciBiZWluZyBsb2dnZWQvc2VudCBmb3IgdGhlIHNhbWUgZGF5LlxuICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmxhc3RTZW50SGVhcnRiZWF0RGF0ZSA9IGRhdGU7XG4gICAgICBpZiAodW5zZW50RW50cmllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIC8vIFN0b3JlIGFueSB1bnNlbnQgZW50cmllcyBpZiB0aGV5IGV4aXN0LlxuICAgICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUuaGVhcnRiZWF0cyA9IHVuc2VudEVudHJpZXM7XG4gICAgICAgIC8vIFRoaXMgc2VlbXMgbW9yZSBsaWtlbHkgdGhhbiBlbXB0eWluZyB0aGUgYXJyYXkgKGJlbG93KSB0byBsZWFkIHRvIHNvbWUgb2RkIHN0YXRlXG4gICAgICAgIC8vIHNpbmNlIHRoZSBjYWNoZSBpc24ndCBlbXB0eSBhbmQgdGhpcyB3aWxsIGJlIGNhbGxlZCBhZ2FpbiBvbiB0aGUgbmV4dCByZXF1ZXN0LFxuICAgICAgICAvLyBhbmQgaXMgcHJvYmFibHkgc2FmZXN0IGlmIHdlIGF3YWl0IGl0LlxuICAgICAgICBhd2FpdCB0aGlzLl9zdG9yYWdlLm92ZXJ3cml0ZSh0aGlzLl9oZWFydGJlYXRzQ2FjaGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmhlYXJ0YmVhdHMgPSBbXTtcbiAgICAgICAgLy8gRG8gbm90IHdhaXQgZm9yIHRoaXMsIHRvIHJlZHVjZSBsYXRlbmN5LlxuICAgICAgICB2b2lkIHRoaXMuX3N0b3JhZ2Uub3ZlcndyaXRlKHRoaXMuX2hlYXJ0YmVhdHNDYWNoZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaGVhZGVyU3RyaW5nO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGUpO1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRVVENEYXRlU3RyaW5nKCk6IHN0cmluZyB7XG4gIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgLy8gUmV0dXJucyBkYXRlIGZvcm1hdCAnWVlZWS1NTS1ERCdcbiAgcmV0dXJuIHRvZGF5LnRvSVNPU3RyaW5nKCkuc3Vic3RyaW5nKDAsIDEwKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RIZWFydGJlYXRzRm9ySGVhZGVyKFxuICBoZWFydGJlYXRzQ2FjaGU6IFNpbmdsZURhdGVIZWFydGJlYXRbXSxcbiAgbWF4U2l6ZSA9IE1BWF9IRUFERVJfQllURVNcbik6IHtcbiAgaGVhcnRiZWF0c1RvU2VuZDogSGVhcnRiZWF0c0J5VXNlckFnZW50W107XG4gIHVuc2VudEVudHJpZXM6IFNpbmdsZURhdGVIZWFydGJlYXRbXTtcbn0ge1xuICAvLyBIZWFydGJlYXRzIGdyb3VwZWQgYnkgdXNlciBhZ2VudCBpbiB0aGUgc3RhbmRhcmQgZm9ybWF0IHRvIGJlIHNlbnQgaW5cbiAgLy8gdGhlIGhlYWRlci5cbiAgY29uc3QgaGVhcnRiZWF0c1RvU2VuZDogSGVhcnRiZWF0c0J5VXNlckFnZW50W10gPSBbXTtcbiAgLy8gU2luZ2xlIGRhdGUgZm9ybWF0IGhlYXJ0YmVhdHMgdGhhdCBhcmUgbm90IHNlbnQuXG4gIGxldCB1bnNlbnRFbnRyaWVzID0gaGVhcnRiZWF0c0NhY2hlLnNsaWNlKCk7XG4gIGZvciAoY29uc3Qgc2luZ2xlRGF0ZUhlYXJ0YmVhdCBvZiBoZWFydGJlYXRzQ2FjaGUpIHtcbiAgICAvLyBMb29rIGZvciBhbiBleGlzdGluZyBlbnRyeSB3aXRoIHRoZSBzYW1lIHVzZXIgYWdlbnQuXG4gICAgY29uc3QgaGVhcnRiZWF0RW50cnkgPSBoZWFydGJlYXRzVG9TZW5kLmZpbmQoXG4gICAgICBoYiA9PiBoYi5hZ2VudCA9PT0gc2luZ2xlRGF0ZUhlYXJ0YmVhdC5hZ2VudFxuICAgICk7XG4gICAgaWYgKCFoZWFydGJlYXRFbnRyeSkge1xuICAgICAgLy8gSWYgbm8gZW50cnkgZm9yIHRoaXMgdXNlciBhZ2VudCBleGlzdHMsIGNyZWF0ZSBvbmUuXG4gICAgICBoZWFydGJlYXRzVG9TZW5kLnB1c2goe1xuICAgICAgICBhZ2VudDogc2luZ2xlRGF0ZUhlYXJ0YmVhdC5hZ2VudCxcbiAgICAgICAgZGF0ZXM6IFtzaW5nbGVEYXRlSGVhcnRiZWF0LmRhdGVdXG4gICAgICB9KTtcbiAgICAgIGlmIChjb3VudEJ5dGVzKGhlYXJ0YmVhdHNUb1NlbmQpID4gbWF4U2l6ZSkge1xuICAgICAgICAvLyBJZiB0aGUgaGVhZGVyIHdvdWxkIGV4Y2VlZCBtYXggc2l6ZSwgcmVtb3ZlIHRoZSBhZGRlZCBoZWFydGJlYXRcbiAgICAgICAgLy8gZW50cnkgYW5kIHN0b3AgYWRkaW5nIHRvIHRoZSBoZWFkZXIuXG4gICAgICAgIGhlYXJ0YmVhdHNUb1NlbmQucG9wKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBoZWFydGJlYXRFbnRyeS5kYXRlcy5wdXNoKHNpbmdsZURhdGVIZWFydGJlYXQuZGF0ZSk7XG4gICAgICAvLyBJZiB0aGUgaGVhZGVyIHdvdWxkIGV4Y2VlZCBtYXggc2l6ZSwgcmVtb3ZlIHRoZSBhZGRlZCBkYXRlXG4gICAgICAvLyBhbmQgc3RvcCBhZGRpbmcgdG8gdGhlIGhlYWRlci5cbiAgICAgIGlmIChjb3VudEJ5dGVzKGhlYXJ0YmVhdHNUb1NlbmQpID4gbWF4U2l6ZSkge1xuICAgICAgICBoZWFydGJlYXRFbnRyeS5kYXRlcy5wb3AoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFBvcCB1bnNlbnQgZW50cnkgZnJvbSBxdWV1ZS4gKFNraXBwZWQgaWYgYWRkaW5nIHRoZSBlbnRyeSBleGNlZWRlZFxuICAgIC8vIHF1b3RhIGFuZCB0aGUgbG9vcCBicmVha3MgZWFybHkuKVxuICAgIHVuc2VudEVudHJpZXMgPSB1bnNlbnRFbnRyaWVzLnNsaWNlKDEpO1xuICB9XG4gIHJldHVybiB7XG4gICAgaGVhcnRiZWF0c1RvU2VuZCxcbiAgICB1bnNlbnRFbnRyaWVzXG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFydGJlYXRTdG9yYWdlSW1wbCBpbXBsZW1lbnRzIEhlYXJ0YmVhdFN0b3JhZ2Uge1xuICBwcml2YXRlIF9jYW5Vc2VJbmRleGVkREJQcm9taXNlOiBQcm9taXNlPGJvb2xlYW4+O1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgYXBwOiBGaXJlYmFzZUFwcCkge1xuICAgIHRoaXMuX2NhblVzZUluZGV4ZWREQlByb21pc2UgPSB0aGlzLnJ1bkluZGV4ZWREQkVudmlyb25tZW50Q2hlY2soKTtcbiAgfVxuICBhc3luYyBydW5JbmRleGVkREJFbnZpcm9ubWVudENoZWNrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmICghaXNJbmRleGVkREJBdmFpbGFibGUoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdmFsaWRhdGVJbmRleGVkREJPcGVuYWJsZSgpXG4gICAgICAgIC50aGVuKCgpID0+IHRydWUpXG4gICAgICAgIC5jYXRjaCgoKSA9PiBmYWxzZSk7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBSZWFkIGFsbCBoZWFydGJlYXRzLlxuICAgKi9cbiAgYXN5bmMgcmVhZCgpOiBQcm9taXNlPEhlYXJ0YmVhdHNJbkluZGV4ZWREQj4ge1xuICAgIGNvbnN0IGNhblVzZUluZGV4ZWREQiA9IGF3YWl0IHRoaXMuX2NhblVzZUluZGV4ZWREQlByb21pc2U7XG4gICAgaWYgKCFjYW5Vc2VJbmRleGVkREIpIHtcbiAgICAgIHJldHVybiB7IGhlYXJ0YmVhdHM6IFtdIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlkYkhlYXJ0YmVhdE9iamVjdCA9IGF3YWl0IHJlYWRIZWFydGJlYXRzRnJvbUluZGV4ZWREQih0aGlzLmFwcCk7XG4gICAgICBpZiAoaWRiSGVhcnRiZWF0T2JqZWN0Py5oZWFydGJlYXRzKSB7XG4gICAgICAgIHJldHVybiBpZGJIZWFydGJlYXRPYmplY3Q7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4geyBoZWFydGJlYXRzOiBbXSB9O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICAvLyBvdmVyd3JpdGUgdGhlIHN0b3JhZ2Ugd2l0aCB0aGUgcHJvdmlkZWQgaGVhcnRiZWF0c1xuICBhc3luYyBvdmVyd3JpdGUoaGVhcnRiZWF0c09iamVjdDogSGVhcnRiZWF0c0luSW5kZXhlZERCKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2FuVXNlSW5kZXhlZERCID0gYXdhaXQgdGhpcy5fY2FuVXNlSW5kZXhlZERCUHJvbWlzZTtcbiAgICBpZiAoIWNhblVzZUluZGV4ZWREQikge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBleGlzdGluZ0hlYXJ0YmVhdHNPYmplY3QgPSBhd2FpdCB0aGlzLnJlYWQoKTtcbiAgICAgIHJldHVybiB3cml0ZUhlYXJ0YmVhdHNUb0luZGV4ZWREQih0aGlzLmFwcCwge1xuICAgICAgICBsYXN0U2VudEhlYXJ0YmVhdERhdGU6XG4gICAgICAgICAgaGVhcnRiZWF0c09iamVjdC5sYXN0U2VudEhlYXJ0YmVhdERhdGUgPz9cbiAgICAgICAgICBleGlzdGluZ0hlYXJ0YmVhdHNPYmplY3QubGFzdFNlbnRIZWFydGJlYXREYXRlLFxuICAgICAgICBoZWFydGJlYXRzOiBoZWFydGJlYXRzT2JqZWN0LmhlYXJ0YmVhdHNcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuICAvLyBhZGQgaGVhcnRiZWF0c1xuICBhc3luYyBhZGQoaGVhcnRiZWF0c09iamVjdDogSGVhcnRiZWF0c0luSW5kZXhlZERCKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2FuVXNlSW5kZXhlZERCID0gYXdhaXQgdGhpcy5fY2FuVXNlSW5kZXhlZERCUHJvbWlzZTtcbiAgICBpZiAoIWNhblVzZUluZGV4ZWREQikge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBleGlzdGluZ0hlYXJ0YmVhdHNPYmplY3QgPSBhd2FpdCB0aGlzLnJlYWQoKTtcbiAgICAgIHJldHVybiB3cml0ZUhlYXJ0YmVhdHNUb0luZGV4ZWREQih0aGlzLmFwcCwge1xuICAgICAgICBsYXN0U2VudEhlYXJ0YmVhdERhdGU6XG4gICAgICAgICAgaGVhcnRiZWF0c09iamVjdC5sYXN0U2VudEhlYXJ0YmVhdERhdGUgPz9cbiAgICAgICAgICBleGlzdGluZ0hlYXJ0YmVhdHNPYmplY3QubGFzdFNlbnRIZWFydGJlYXREYXRlLFxuICAgICAgICBoZWFydGJlYXRzOiBbXG4gICAgICAgICAgLi4uZXhpc3RpbmdIZWFydGJlYXRzT2JqZWN0LmhlYXJ0YmVhdHMsXG4gICAgICAgICAgLi4uaGVhcnRiZWF0c09iamVjdC5oZWFydGJlYXRzXG4gICAgICAgIF1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBieXRlcyBvZiBhIEhlYXJ0YmVhdHNCeVVzZXJBZ2VudCBhcnJheSBhZnRlciBiZWluZyB3cmFwcGVkXG4gKiBpbiBhIHBsYXRmb3JtIGxvZ2dpbmcgaGVhZGVyIEpTT04gb2JqZWN0LCBzdHJpbmdpZmllZCwgYW5kIGNvbnZlcnRlZFxuICogdG8gYmFzZSA2NC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50Qnl0ZXMoaGVhcnRiZWF0c0NhY2hlOiBIZWFydGJlYXRzQnlVc2VyQWdlbnRbXSk6IG51bWJlciB7XG4gIC8vIGJhc2U2NCBoYXMgYSByZXN0cmljdGVkIHNldCBvZiBjaGFyYWN0ZXJzLCBhbGwgb2Ygd2hpY2ggc2hvdWxkIGJlIDEgYnl0ZS5cbiAgcmV0dXJuIGJhc2U2NHVybEVuY29kZVdpdGhvdXRQYWRkaW5nKFxuICAgIC8vIGhlYXJ0YmVhdHNDYWNoZSB3cmFwcGVyIHByb3BlcnRpZXNcbiAgICBKU09OLnN0cmluZ2lmeSh7IHZlcnNpb246IDIsIGhlYXJ0YmVhdHM6IGhlYXJ0YmVhdHNDYWNoZSB9KVxuICApLmxlbmd0aDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgaGVhcnRiZWF0IHdpdGggdGhlIGVhcmxpZXN0IGRhdGUuXG4gKiBJZiB0aGUgaGVhcnRiZWF0cyBhcnJheSBpcyBlbXB0eSwgLTEgaXMgcmV0dXJuZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFYXJsaWVzdEhlYXJ0YmVhdElkeChcbiAgaGVhcnRiZWF0czogU2luZ2xlRGF0ZUhlYXJ0YmVhdFtdXG4pOiBudW1iZXIge1xuICBpZiAoaGVhcnRiZWF0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICBsZXQgZWFybGllc3RIZWFydGJlYXRJZHggPSAwO1xuICBsZXQgZWFybGllc3RIZWFydGJlYXREYXRlID0gaGVhcnRiZWF0c1swXS5kYXRlO1xuXG4gIGZvciAobGV0IGkgPSAxOyBpIDwgaGVhcnRiZWF0cy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChoZWFydGJlYXRzW2ldLmRhdGUgPCBlYXJsaWVzdEhlYXJ0YmVhdERhdGUpIHtcbiAgICAgIGVhcmxpZXN0SGVhcnRiZWF0RGF0ZSA9IGhlYXJ0YmVhdHNbaV0uZGF0ZTtcbiAgICAgIGVhcmxpZXN0SGVhcnRiZWF0SWR4ID0gaTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZWFybGllc3RIZWFydGJlYXRJZHg7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQ29tcG9uZW50LCBDb21wb25lbnRUeXBlIH0gZnJvbSAnQGZpcmViYXNlL2NvbXBvbmVudCc7XG5pbXBvcnQgeyBQbGF0Zm9ybUxvZ2dlclNlcnZpY2VJbXBsIH0gZnJvbSAnLi9wbGF0Zm9ybUxvZ2dlclNlcnZpY2UnO1xuaW1wb3J0IHsgbmFtZSwgdmVyc2lvbiB9IGZyb20gJy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBfcmVnaXN0ZXJDb21wb25lbnQgfSBmcm9tICcuL2ludGVybmFsJztcbmltcG9ydCB7IHJlZ2lzdGVyVmVyc2lvbiB9IGZyb20gJy4vYXBpJztcbmltcG9ydCB7IEhlYXJ0YmVhdFNlcnZpY2VJbXBsIH0gZnJvbSAnLi9oZWFydGJlYXRTZXJ2aWNlJztcblxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQ29yZUNvbXBvbmVudHModmFyaWFudD86IHN0cmluZyk6IHZvaWQge1xuICBfcmVnaXN0ZXJDb21wb25lbnQoXG4gICAgbmV3IENvbXBvbmVudChcbiAgICAgICdwbGF0Zm9ybS1sb2dnZXInLFxuICAgICAgY29udGFpbmVyID0+IG5ldyBQbGF0Zm9ybUxvZ2dlclNlcnZpY2VJbXBsKGNvbnRhaW5lciksXG4gICAgICBDb21wb25lbnRUeXBlLlBSSVZBVEVcbiAgICApXG4gICk7XG4gIF9yZWdpc3RlckNvbXBvbmVudChcbiAgICBuZXcgQ29tcG9uZW50KFxuICAgICAgJ2hlYXJ0YmVhdCcsXG4gICAgICBjb250YWluZXIgPT4gbmV3IEhlYXJ0YmVhdFNlcnZpY2VJbXBsKGNvbnRhaW5lciksXG4gICAgICBDb21wb25lbnRUeXBlLlBSSVZBVEVcbiAgICApXG4gICk7XG5cbiAgLy8gUmVnaXN0ZXIgYGFwcGAgcGFja2FnZS5cbiAgcmVnaXN0ZXJWZXJzaW9uKG5hbWUsIHZlcnNpb24sIHZhcmlhbnQpO1xuICAvLyBCVUlMRF9UQVJHRVQgd2lsbCBiZSByZXBsYWNlZCBieSB2YWx1ZXMgbGlrZSBlc20sIGNqcywgZXRjIGR1cmluZyB0aGUgY29tcGlsYXRpb25cbiAgcmVnaXN0ZXJWZXJzaW9uKG5hbWUsIHZlcnNpb24sICdfX0JVSUxEX1RBUkdFVF9fJyk7XG4gIC8vIFJlZ2lzdGVyIHBsYXRmb3JtIFNESyBpZGVudGlmaWVyIChubyB2ZXJzaW9uKS5cbiAgcmVnaXN0ZXJWZXJzaW9uKCdmaXJlLWpzJywgJycpO1xufVxuIiwgIi8qKlxuICogRmlyZWJhc2UgQXBwXG4gKlxuICogQHJlbWFya3MgVGhpcyBwYWNrYWdlIGNvb3JkaW5hdGVzIHRoZSBjb21tdW5pY2F0aW9uIGJldHdlZW4gdGhlIGRpZmZlcmVudCBGaXJlYmFzZSBjb21wb25lbnRzXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuXG4vKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyByZWdpc3RlckNvcmVDb21wb25lbnRzIH0gZnJvbSAnLi9yZWdpc3RlckNvcmVDb21wb25lbnRzJztcblxuZXhwb3J0ICogZnJvbSAnLi9hcGknO1xuZXhwb3J0ICogZnJvbSAnLi9pbnRlcm5hbCc7XG5leHBvcnQgKiBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5cbnJlZ2lzdGVyQ29yZUNvbXBvbmVudHMoJ19fUlVOVElNRV9FTlZfXycpO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5pbXBvcnQgeyByZWdpc3RlclZlcnNpb24gfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IG5hbWUsIHZlcnNpb24gfSBmcm9tICcuLi9wYWNrYWdlLmpzb24nO1xuXG5yZWdpc3RlclZlcnNpb24obmFtZSwgdmVyc2lvbiwgJ2FwcCcpO1xuZXhwb3J0ICogZnJvbSAnQGZpcmViYXNlL2FwcCc7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBBbiBlbnVtIG9mIGZhY3RvcnMgdGhhdCBtYXkgYmUgdXNlZCBmb3IgbXVsdGlmYWN0b3IgYXV0aGVudGljYXRpb24uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgRmFjdG9ySWQgPSB7XG4gIC8qKiBQaG9uZSBhcyBzZWNvbmQgZmFjdG9yICovXG4gIFBIT05FOiAncGhvbmUnLFxuICBUT1RQOiAndG90cCdcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogRW51bWVyYXRpb24gb2Ygc3VwcG9ydGVkIHByb3ZpZGVycy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBQcm92aWRlcklkID0ge1xuICAvKiogRmFjZWJvb2sgcHJvdmlkZXIgSUQgKi9cbiAgRkFDRUJPT0s6ICdmYWNlYm9vay5jb20nLFxuICAvKiogR2l0SHViIHByb3ZpZGVyIElEICovXG4gIEdJVEhVQjogJ2dpdGh1Yi5jb20nLFxuICAvKiogR29vZ2xlIHByb3ZpZGVyIElEICovXG4gIEdPT0dMRTogJ2dvb2dsZS5jb20nLFxuICAvKiogUGFzc3dvcmQgcHJvdmlkZXIgKi9cbiAgUEFTU1dPUkQ6ICdwYXNzd29yZCcsXG4gIC8qKiBQaG9uZSBwcm92aWRlciAqL1xuICBQSE9ORTogJ3Bob25lJyxcbiAgLyoqIFR3aXR0ZXIgcHJvdmlkZXIgSUQgKi9cbiAgVFdJVFRFUjogJ3R3aXR0ZXIuY29tJ1xufSBhcyBjb25zdDtcblxuLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiBzdXBwb3J0ZWQgc2lnbi1pbiBtZXRob2RzLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IFNpZ25Jbk1ldGhvZCA9IHtcbiAgLyoqIEVtYWlsIGxpbmsgc2lnbiBpbiBtZXRob2QgKi9cbiAgRU1BSUxfTElOSzogJ2VtYWlsTGluaycsXG4gIC8qKiBFbWFpbC9wYXNzd29yZCBzaWduIGluIG1ldGhvZCAqL1xuICBFTUFJTF9QQVNTV09SRDogJ3Bhc3N3b3JkJyxcbiAgLyoqIEZhY2Vib29rIHNpZ24gaW4gbWV0aG9kICovXG4gIEZBQ0VCT09LOiAnZmFjZWJvb2suY29tJyxcbiAgLyoqIEdpdEh1YiBzaWduIGluIG1ldGhvZCAqL1xuICBHSVRIVUI6ICdnaXRodWIuY29tJyxcbiAgLyoqIEdvb2dsZSBzaWduIGluIG1ldGhvZCAqL1xuICBHT09HTEU6ICdnb29nbGUuY29tJyxcbiAgLyoqIFBob25lIHNpZ24gaW4gbWV0aG9kICovXG4gIFBIT05FOiAncGhvbmUnLFxuICAvKiogVHdpdHRlciBzaWduIGluIG1ldGhvZCAqL1xuICBUV0lUVEVSOiAndHdpdHRlci5jb20nXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIHN1cHBvcnRlZCBvcGVyYXRpb24gdHlwZXMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgT3BlcmF0aW9uVHlwZSA9IHtcbiAgLyoqIE9wZXJhdGlvbiBpbnZvbHZpbmcgbGlua2luZyBhbiBhZGRpdGlvbmFsIHByb3ZpZGVyIHRvIGFuIGFscmVhZHkgc2lnbmVkLWluIHVzZXIuICovXG4gIExJTks6ICdsaW5rJyxcbiAgLyoqIE9wZXJhdGlvbiBpbnZvbHZpbmcgdXNpbmcgYSBwcm92aWRlciB0byByZWF1dGhlbnRpY2F0ZSBhbiBhbHJlYWR5IHNpZ25lZC1pbiB1c2VyLiAqL1xuICBSRUFVVEhFTlRJQ0FURTogJ3JlYXV0aGVudGljYXRlJyxcbiAgLyoqIE9wZXJhdGlvbiBpbnZvbHZpbmcgc2lnbmluZyBpbiBhIHVzZXIuICovXG4gIFNJR05fSU46ICdzaWduSW4nXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEFuIGVudW1lcmF0aW9uIG9mIHRoZSBwb3NzaWJsZSBlbWFpbCBhY3Rpb24gdHlwZXMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgQWN0aW9uQ29kZU9wZXJhdGlvbiA9IHtcbiAgLyoqIFRoZSBlbWFpbCBsaW5rIHNpZ24taW4gYWN0aW9uLiAqL1xuICBFTUFJTF9TSUdOSU46ICdFTUFJTF9TSUdOSU4nLFxuICAvKiogVGhlIHBhc3N3b3JkIHJlc2V0IGFjdGlvbi4gKi9cbiAgUEFTU1dPUkRfUkVTRVQ6ICdQQVNTV09SRF9SRVNFVCcsXG4gIC8qKiBUaGUgZW1haWwgcmV2b2NhdGlvbiBhY3Rpb24uICovXG4gIFJFQ09WRVJfRU1BSUw6ICdSRUNPVkVSX0VNQUlMJyxcbiAgLyoqIFRoZSByZXZlcnQgc2Vjb25kIGZhY3RvciBhZGRpdGlvbiBlbWFpbCBhY3Rpb24uICovXG4gIFJFVkVSVF9TRUNPTkRfRkFDVE9SX0FERElUSU9OOiAnUkVWRVJUX1NFQ09ORF9GQUNUT1JfQURESVRJT04nLFxuICAvKiogVGhlIHJldmVydCBzZWNvbmQgZmFjdG9yIGFkZGl0aW9uIGVtYWlsIGFjdGlvbi4gKi9cbiAgVkVSSUZZX0FORF9DSEFOR0VfRU1BSUw6ICdWRVJJRllfQU5EX0NIQU5HRV9FTUFJTCcsXG4gIC8qKiBUaGUgZW1haWwgdmVyaWZpY2F0aW9uIGFjdGlvbi4gKi9cbiAgVkVSSUZZX0VNQUlMOiAnVkVSSUZZX0VNQUlMJ1xufSBhcyBjb25zdDtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JNYXAsIFVzZXIgfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgRXJyb3JGYWN0b3J5LCBFcnJvck1hcCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgSWRUb2tlbk1mYVJlc3BvbnNlIH0gZnJvbSAnLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBBcHBOYW1lIH0gZnJvbSAnLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vY3JlZGVudGlhbHMnO1xuXG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIEZpcmViYXNlIEF1dGggZXJyb3IgY29kZXMuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBlbnVtIEF1dGhFcnJvckNvZGUge1xuICBBRE1JTl9PTkxZX09QRVJBVElPTiA9ICdhZG1pbi1yZXN0cmljdGVkLW9wZXJhdGlvbicsXG4gIEFSR1VNRU5UX0VSUk9SID0gJ2FyZ3VtZW50LWVycm9yJyxcbiAgQVBQX05PVF9BVVRIT1JJWkVEID0gJ2FwcC1ub3QtYXV0aG9yaXplZCcsXG4gIEFQUF9OT1RfSU5TVEFMTEVEID0gJ2FwcC1ub3QtaW5zdGFsbGVkJyxcbiAgQ0FQVENIQV9DSEVDS19GQUlMRUQgPSAnY2FwdGNoYS1jaGVjay1mYWlsZWQnLFxuICBDT0RFX0VYUElSRUQgPSAnY29kZS1leHBpcmVkJyxcbiAgQ09SRE9WQV9OT1RfUkVBRFkgPSAnY29yZG92YS1ub3QtcmVhZHknLFxuICBDT1JTX1VOU1VQUE9SVEVEID0gJ2NvcnMtdW5zdXBwb3J0ZWQnLFxuICBDUkVERU5USUFMX0FMUkVBRFlfSU5fVVNFID0gJ2NyZWRlbnRpYWwtYWxyZWFkeS1pbi11c2UnLFxuICBDUkVERU5USUFMX01JU01BVENIID0gJ2N1c3RvbS10b2tlbi1taXNtYXRjaCcsXG4gIENSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTiA9ICdyZXF1aXJlcy1yZWNlbnQtbG9naW4nLFxuICBERVBFTkRFTlRfU0RLX0lOSVRfQkVGT1JFX0FVVEggPSAnZGVwZW5kZW50LXNkay1pbml0aWFsaXplZC1iZWZvcmUtYXV0aCcsXG4gIERZTkFNSUNfTElOS19OT1RfQUNUSVZBVEVEID0gJ2R5bmFtaWMtbGluay1ub3QtYWN0aXZhdGVkJyxcbiAgRU1BSUxfQ0hBTkdFX05FRURTX1ZFUklGSUNBVElPTiA9ICdlbWFpbC1jaGFuZ2UtbmVlZHMtdmVyaWZpY2F0aW9uJyxcbiAgRU1BSUxfRVhJU1RTID0gJ2VtYWlsLWFscmVhZHktaW4tdXNlJyxcbiAgRU1VTEFUT1JfQ09ORklHX0ZBSUxFRCA9ICdlbXVsYXRvci1jb25maWctZmFpbGVkJyxcbiAgRVhQSVJFRF9PT0JfQ09ERSA9ICdleHBpcmVkLWFjdGlvbi1jb2RlJyxcbiAgRVhQSVJFRF9QT1BVUF9SRVFVRVNUID0gJ2NhbmNlbGxlZC1wb3B1cC1yZXF1ZXN0JyxcbiAgSU5URVJOQUxfRVJST1IgPSAnaW50ZXJuYWwtZXJyb3InLFxuICBJTlZBTElEX0FQSV9LRVkgPSAnaW52YWxpZC1hcGkta2V5JyxcbiAgSU5WQUxJRF9BUFBfQ1JFREVOVElBTCA9ICdpbnZhbGlkLWFwcC1jcmVkZW50aWFsJyxcbiAgSU5WQUxJRF9BUFBfSUQgPSAnaW52YWxpZC1hcHAtaWQnLFxuICBJTlZBTElEX0FVVEggPSAnaW52YWxpZC11c2VyLXRva2VuJyxcbiAgSU5WQUxJRF9BVVRIX0VWRU5UID0gJ2ludmFsaWQtYXV0aC1ldmVudCcsXG4gIElOVkFMSURfQ0VSVF9IQVNIID0gJ2ludmFsaWQtY2VydC1oYXNoJyxcbiAgSU5WQUxJRF9DT0RFID0gJ2ludmFsaWQtdmVyaWZpY2F0aW9uLWNvZGUnLFxuICBJTlZBTElEX0NPTlRJTlVFX1VSSSA9ICdpbnZhbGlkLWNvbnRpbnVlLXVyaScsXG4gIElOVkFMSURfQ09SRE9WQV9DT05GSUdVUkFUSU9OID0gJ2ludmFsaWQtY29yZG92YS1jb25maWd1cmF0aW9uJyxcbiAgSU5WQUxJRF9DVVNUT01fVE9LRU4gPSAnaW52YWxpZC1jdXN0b20tdG9rZW4nLFxuICBJTlZBTElEX0RZTkFNSUNfTElOS19ET01BSU4gPSAnaW52YWxpZC1keW5hbWljLWxpbmstZG9tYWluJyxcbiAgSU5WQUxJRF9FTUFJTCA9ICdpbnZhbGlkLWVtYWlsJyxcbiAgSU5WQUxJRF9FTVVMQVRPUl9TQ0hFTUUgPSAnaW52YWxpZC1lbXVsYXRvci1zY2hlbWUnLFxuICBJTlZBTElEX0NSRURFTlRJQUwgPSAnaW52YWxpZC1jcmVkZW50aWFsJyxcbiAgSU5WQUxJRF9NRVNTQUdFX1BBWUxPQUQgPSAnaW52YWxpZC1tZXNzYWdlLXBheWxvYWQnLFxuICBJTlZBTElEX01GQV9TRVNTSU9OID0gJ2ludmFsaWQtbXVsdGktZmFjdG9yLXNlc3Npb24nLFxuICBJTlZBTElEX09BVVRIX0NMSUVOVF9JRCA9ICdpbnZhbGlkLW9hdXRoLWNsaWVudC1pZCcsXG4gIElOVkFMSURfT0FVVEhfUFJPVklERVIgPSAnaW52YWxpZC1vYXV0aC1wcm92aWRlcicsXG4gIElOVkFMSURfT09CX0NPREUgPSAnaW52YWxpZC1hY3Rpb24tY29kZScsXG4gIElOVkFMSURfT1JJR0lOID0gJ3VuYXV0aG9yaXplZC1kb21haW4nLFxuICBJTlZBTElEX1BBU1NXT1JEID0gJ3dyb25nLXBhc3N3b3JkJyxcbiAgSU5WQUxJRF9QRVJTSVNURU5DRSA9ICdpbnZhbGlkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBJTlZBTElEX1BIT05FX05VTUJFUiA9ICdpbnZhbGlkLXBob25lLW51bWJlcicsXG4gIElOVkFMSURfUFJPVklERVJfSUQgPSAnaW52YWxpZC1wcm92aWRlci1pZCcsXG4gIElOVkFMSURfUkVDSVBJRU5UX0VNQUlMID0gJ2ludmFsaWQtcmVjaXBpZW50LWVtYWlsJyxcbiAgSU5WQUxJRF9TRU5ERVIgPSAnaW52YWxpZC1zZW5kZXInLFxuICBJTlZBTElEX1NFU1NJT05fSU5GTyA9ICdpbnZhbGlkLXZlcmlmaWNhdGlvbi1pZCcsXG4gIElOVkFMSURfVEVOQU5UX0lEID0gJ2ludmFsaWQtdGVuYW50LWlkJyxcbiAgTE9HSU5fQkxPQ0tFRCA9ICdsb2dpbi1ibG9ja2VkJyxcbiAgTUZBX0lORk9fTk9UX0ZPVU5EID0gJ211bHRpLWZhY3Rvci1pbmZvLW5vdC1mb3VuZCcsXG4gIE1GQV9SRVFVSVJFRCA9ICdtdWx0aS1mYWN0b3ItYXV0aC1yZXF1aXJlZCcsXG4gIE1JU1NJTkdfQU5EUk9JRF9QQUNLQUdFX05BTUUgPSAnbWlzc2luZy1hbmRyb2lkLXBrZy1uYW1lJyxcbiAgTUlTU0lOR19BUFBfQ1JFREVOVElBTCA9ICdtaXNzaW5nLWFwcC1jcmVkZW50aWFsJyxcbiAgTUlTU0lOR19BVVRIX0RPTUFJTiA9ICdhdXRoLWRvbWFpbi1jb25maWctcmVxdWlyZWQnLFxuICBNSVNTSU5HX0NPREUgPSAnbWlzc2luZy12ZXJpZmljYXRpb24tY29kZScsXG4gIE1JU1NJTkdfQ09OVElOVUVfVVJJID0gJ21pc3NpbmctY29udGludWUtdXJpJyxcbiAgTUlTU0lOR19JRlJBTUVfU1RBUlQgPSAnbWlzc2luZy1pZnJhbWUtc3RhcnQnLFxuICBNSVNTSU5HX0lPU19CVU5ETEVfSUQgPSAnbWlzc2luZy1pb3MtYnVuZGxlLWlkJyxcbiAgTUlTU0lOR19PUl9JTlZBTElEX05PTkNFID0gJ21pc3Npbmctb3ItaW52YWxpZC1ub25jZScsXG4gIE1JU1NJTkdfTUZBX0lORk8gPSAnbWlzc2luZy1tdWx0aS1mYWN0b3ItaW5mbycsXG4gIE1JU1NJTkdfTUZBX1NFU1NJT04gPSAnbWlzc2luZy1tdWx0aS1mYWN0b3Itc2Vzc2lvbicsXG4gIE1JU1NJTkdfUEhPTkVfTlVNQkVSID0gJ21pc3NpbmctcGhvbmUtbnVtYmVyJyxcbiAgTUlTU0lOR19QQVNTV09SRCA9ICdtaXNzaW5nLXBhc3N3b3JkJyxcbiAgTUlTU0lOR19TRVNTSU9OX0lORk8gPSAnbWlzc2luZy12ZXJpZmljYXRpb24taWQnLFxuICBNT0RVTEVfREVTVFJPWUVEID0gJ2FwcC1kZWxldGVkJyxcbiAgTkVFRF9DT05GSVJNQVRJT04gPSAnYWNjb3VudC1leGlzdHMtd2l0aC1kaWZmZXJlbnQtY3JlZGVudGlhbCcsXG4gIE5FVFdPUktfUkVRVUVTVF9GQUlMRUQgPSAnbmV0d29yay1yZXF1ZXN0LWZhaWxlZCcsXG4gIE5VTExfVVNFUiA9ICdudWxsLXVzZXInLFxuICBOT19BVVRIX0VWRU5UID0gJ25vLWF1dGgtZXZlbnQnLFxuICBOT19TVUNIX1BST1ZJREVSID0gJ25vLXN1Y2gtcHJvdmlkZXInLFxuICBPUEVSQVRJT05fTk9UX0FMTE9XRUQgPSAnb3BlcmF0aW9uLW5vdC1hbGxvd2VkJyxcbiAgT1BFUkFUSU9OX05PVF9TVVBQT1JURUQgPSAnb3BlcmF0aW9uLW5vdC1zdXBwb3J0ZWQtaW4tdGhpcy1lbnZpcm9ubWVudCcsXG4gIFBPUFVQX0JMT0NLRUQgPSAncG9wdXAtYmxvY2tlZCcsXG4gIFBPUFVQX0NMT1NFRF9CWV9VU0VSID0gJ3BvcHVwLWNsb3NlZC1ieS11c2VyJyxcbiAgUFJPVklERVJfQUxSRUFEWV9MSU5LRUQgPSAncHJvdmlkZXItYWxyZWFkeS1saW5rZWQnLFxuICBRVU9UQV9FWENFRURFRCA9ICdxdW90YS1leGNlZWRlZCcsXG4gIFJFRElSRUNUX0NBTkNFTExFRF9CWV9VU0VSID0gJ3JlZGlyZWN0LWNhbmNlbGxlZC1ieS11c2VyJyxcbiAgUkVESVJFQ1RfT1BFUkFUSU9OX1BFTkRJTkcgPSAncmVkaXJlY3Qtb3BlcmF0aW9uLXBlbmRpbmcnLFxuICBSRUpFQ1RFRF9DUkVERU5USUFMID0gJ3JlamVjdGVkLWNyZWRlbnRpYWwnLFxuICBTRUNPTkRfRkFDVE9SX0FMUkVBRFlfRU5ST0xMRUQgPSAnc2Vjb25kLWZhY3Rvci1hbHJlYWR5LWluLXVzZScsXG4gIFNFQ09ORF9GQUNUT1JfTElNSVRfRVhDRUVERUQgPSAnbWF4aW11bS1zZWNvbmQtZmFjdG9yLWNvdW50LWV4Y2VlZGVkJyxcbiAgVEVOQU5UX0lEX01JU01BVENIID0gJ3RlbmFudC1pZC1taXNtYXRjaCcsXG4gIFRJTUVPVVQgPSAndGltZW91dCcsXG4gIFRPS0VOX0VYUElSRUQgPSAndXNlci10b2tlbi1leHBpcmVkJyxcbiAgVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSID0gJ3Rvby1tYW55LXJlcXVlc3RzJyxcbiAgVU5BVVRIT1JJWkVEX0RPTUFJTiA9ICd1bmF1dGhvcml6ZWQtY29udGludWUtdXJpJyxcbiAgVU5TVVBQT1JURURfRklSU1RfRkFDVE9SID0gJ3Vuc3VwcG9ydGVkLWZpcnN0LWZhY3RvcicsXG4gIFVOU1VQUE9SVEVEX1BFUlNJU1RFTkNFID0gJ3Vuc3VwcG9ydGVkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBVTlNVUFBPUlRFRF9URU5BTlRfT1BFUkFUSU9OID0gJ3Vuc3VwcG9ydGVkLXRlbmFudC1vcGVyYXRpb24nLFxuICBVTlZFUklGSUVEX0VNQUlMID0gJ3VudmVyaWZpZWQtZW1haWwnLFxuICBVU0VSX0NBTkNFTExFRCA9ICd1c2VyLWNhbmNlbGxlZCcsXG4gIFVTRVJfREVMRVRFRCA9ICd1c2VyLW5vdC1mb3VuZCcsXG4gIFVTRVJfRElTQUJMRUQgPSAndXNlci1kaXNhYmxlZCcsXG4gIFVTRVJfTUlTTUFUQ0ggPSAndXNlci1taXNtYXRjaCcsXG4gIFVTRVJfU0lHTkVEX09VVCA9ICd1c2VyLXNpZ25lZC1vdXQnLFxuICBXRUFLX1BBU1NXT1JEID0gJ3dlYWstcGFzc3dvcmQnLFxuICBXRUJfU1RPUkFHRV9VTlNVUFBPUlRFRCA9ICd3ZWItc3RvcmFnZS11bnN1cHBvcnRlZCcsXG4gIEFMUkVBRFlfSU5JVElBTElaRUQgPSAnYWxyZWFkeS1pbml0aWFsaXplZCcsXG4gIFJFQ0FQVENIQV9OT1RfRU5BQkxFRCA9ICdyZWNhcHRjaGEtbm90LWVuYWJsZWQnLFxuICBNSVNTSU5HX1JFQ0FQVENIQV9UT0tFTiA9ICdtaXNzaW5nLXJlY2FwdGNoYS10b2tlbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX1RPS0VOID0gJ2ludmFsaWQtcmVjYXB0Y2hhLXRva2VuJyxcbiAgSU5WQUxJRF9SRUNBUFRDSEFfQUNUSU9OID0gJ2ludmFsaWQtcmVjYXB0Y2hhLWFjdGlvbicsXG4gIE1JU1NJTkdfQ0xJRU5UX1RZUEUgPSAnbWlzc2luZy1jbGllbnQtdHlwZScsXG4gIE1JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT04gPSAnbWlzc2luZy1yZWNhcHRjaGEtdmVyc2lvbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX1ZFUlNJT04gPSAnaW52YWxpZC1yZWNhcHRjaGEtdmVyc2lvbicsXG4gIElOVkFMSURfUkVRX1RZUEUgPSAnaW52YWxpZC1yZXEtdHlwZScsXG4gIFVOU1VQUE9SVEVEX1BBU1NXT1JEX1BPTElDWV9TQ0hFTUFfVkVSU0lPTiA9ICd1bnN1cHBvcnRlZC1wYXNzd29yZC1wb2xpY3ktc2NoZW1hLXZlcnNpb24nLFxuICBQQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UUyA9ICdwYXNzd29yZC1kb2VzLW5vdC1tZWV0LXJlcXVpcmVtZW50cycsXG4gIElOVkFMSURfSE9TVElOR19MSU5LX0RPTUFJTiA9ICdpbnZhbGlkLWhvc3RpbmctbGluay1kb21haW4nXG59XG5cbmZ1bmN0aW9uIF9kZWJ1Z0Vycm9yTWFwKCk6IEVycm9yTWFwPEF1dGhFcnJvckNvZGU+IHtcbiAgcmV0dXJuIHtcbiAgICBbQXV0aEVycm9yQ29kZS5BRE1JTl9PTkxZX09QRVJBVElPTl06XG4gICAgICAnVGhpcyBvcGVyYXRpb24gaXMgcmVzdHJpY3RlZCB0byBhZG1pbmlzdHJhdG9ycyBvbmx5LicsXG4gICAgW0F1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JdOiAnJyxcbiAgICBbQXV0aEVycm9yQ29kZS5BUFBfTk9UX0FVVEhPUklaRURdOlxuICAgICAgXCJUaGlzIGFwcCwgaWRlbnRpZmllZCBieSB0aGUgZG9tYWluIHdoZXJlIGl0J3MgaG9zdGVkLCBpcyBub3QgXCIgK1xuICAgICAgJ2F1dGhvcml6ZWQgdG8gdXNlIEZpcmViYXNlIEF1dGhlbnRpY2F0aW9uIHdpdGggdGhlIHByb3ZpZGVkIEFQSSBrZXkuICcgK1xuICAgICAgJ1JldmlldyB5b3VyIGtleSBjb25maWd1cmF0aW9uIGluIHRoZSBHb29nbGUgQVBJIGNvbnNvbGUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5BUFBfTk9UX0lOU1RBTExFRF06XG4gICAgICAnVGhlIHJlcXVlc3RlZCBtb2JpbGUgYXBwbGljYXRpb24gY29ycmVzcG9uZGluZyB0byB0aGUgaWRlbnRpZmllciAoJyArXG4gICAgICAnQW5kcm9pZCBwYWNrYWdlIG5hbWUgb3IgaU9TIGJ1bmRsZSBJRCkgcHJvdmlkZWQgaXMgbm90IGluc3RhbGxlZCBvbiAnICtcbiAgICAgICd0aGlzIGRldmljZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkNBUFRDSEFfQ0hFQ0tfRkFJTEVEXTpcbiAgICAgICdUaGUgcmVDQVBUQ0hBIHJlc3BvbnNlIHRva2VuIHByb3ZpZGVkIGlzIGVpdGhlciBpbnZhbGlkLCBleHBpcmVkLCAnICtcbiAgICAgICdhbHJlYWR5IHVzZWQgb3IgdGhlIGRvbWFpbiBhc3NvY2lhdGVkIHdpdGggaXQgZG9lcyBub3QgbWF0Y2ggdGhlIGxpc3QgJyArXG4gICAgICAnb2Ygd2hpdGVsaXN0ZWQgZG9tYWlucy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkNPREVfRVhQSVJFRF06XG4gICAgICAnVGhlIFNNUyBjb2RlIGhhcyBleHBpcmVkLiBQbGVhc2UgcmUtc2VuZCB0aGUgdmVyaWZpY2F0aW9uIGNvZGUgdG8gdHJ5ICcgK1xuICAgICAgJ2FnYWluLicsXG4gICAgW0F1dGhFcnJvckNvZGUuQ09SRE9WQV9OT1RfUkVBRFldOiAnQ29yZG92YSBmcmFtZXdvcmsgaXMgbm90IHJlYWR5LicsXG4gICAgW0F1dGhFcnJvckNvZGUuQ09SU19VTlNVUFBPUlRFRF06ICdUaGlzIGJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkNSRURFTlRJQUxfQUxSRUFEWV9JTl9VU0VdOlxuICAgICAgJ1RoaXMgY3JlZGVudGlhbCBpcyBhbHJlYWR5IGFzc29jaWF0ZWQgd2l0aCBhIGRpZmZlcmVudCB1c2VyIGFjY291bnQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5DUkVERU5USUFMX01JU01BVENIXTpcbiAgICAgICdUaGUgY3VzdG9tIHRva2VuIGNvcnJlc3BvbmRzIHRvIGEgZGlmZmVyZW50IGF1ZGllbmNlLicsXG4gICAgW0F1dGhFcnJvckNvZGUuQ1JFREVOVElBTF9UT09fT0xEX0xPR0lOX0FHQUlOXTpcbiAgICAgICdUaGlzIG9wZXJhdGlvbiBpcyBzZW5zaXRpdmUgYW5kIHJlcXVpcmVzIHJlY2VudCBhdXRoZW50aWNhdGlvbi4gTG9nIGluICcgK1xuICAgICAgJ2FnYWluIGJlZm9yZSByZXRyeWluZyB0aGlzIHJlcXVlc3QuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5ERVBFTkRFTlRfU0RLX0lOSVRfQkVGT1JFX0FVVEhdOlxuICAgICAgJ0Fub3RoZXIgRmlyZWJhc2UgU0RLIHdhcyBpbml0aWFsaXplZCBhbmQgaXMgdHJ5aW5nIHRvIHVzZSBBdXRoIGJlZm9yZSBBdXRoIGlzICcgK1xuICAgICAgJ2luaXRpYWxpemVkLiBQbGVhc2UgYmUgc3VyZSB0byBjYWxsIGBpbml0aWFsaXplQXV0aGAgb3IgYGdldEF1dGhgIGJlZm9yZSAnICtcbiAgICAgICdzdGFydGluZyBhbnkgb3RoZXIgRmlyZWJhc2UgU0RLLicsXG4gICAgW0F1dGhFcnJvckNvZGUuRFlOQU1JQ19MSU5LX05PVF9BQ1RJVkFURURdOlxuICAgICAgJ1BsZWFzZSBhY3RpdmF0ZSBEeW5hbWljIExpbmtzIGluIHRoZSBGaXJlYmFzZSBDb25zb2xlIGFuZCBhZ3JlZSB0byB0aGUgdGVybXMgYW5kICcgK1xuICAgICAgJ2NvbmRpdGlvbnMuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5FTUFJTF9DSEFOR0VfTkVFRFNfVkVSSUZJQ0FUSU9OXTpcbiAgICAgICdNdWx0aS1mYWN0b3IgdXNlcnMgbXVzdCBhbHdheXMgaGF2ZSBhIHZlcmlmaWVkIGVtYWlsLicsXG4gICAgW0F1dGhFcnJvckNvZGUuRU1BSUxfRVhJU1RTXTpcbiAgICAgICdUaGUgZW1haWwgYWRkcmVzcyBpcyBhbHJlYWR5IGluIHVzZSBieSBhbm90aGVyIGFjY291bnQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5FTVVMQVRPUl9DT05GSUdfRkFJTEVEXTpcbiAgICAgICdBdXRoIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gdXNlZCB0byBtYWtlIGEgbmV0d29yayBjYWxsLiBBdXRoIGNhbiAnICtcbiAgICAgICdubyBsb25nZXIgYmUgY29uZmlndXJlZCB0byB1c2UgdGhlIGVtdWxhdG9yLiBUcnkgY2FsbGluZyAnICtcbiAgICAgICdcImNvbm5lY3RBdXRoRW11bGF0b3IoKVwiIHNvb25lci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkVYUElSRURfT09CX0NPREVdOiAnVGhlIGFjdGlvbiBjb2RlIGhhcyBleHBpcmVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuRVhQSVJFRF9QT1BVUF9SRVFVRVNUXTpcbiAgICAgICdUaGlzIG9wZXJhdGlvbiBoYXMgYmVlbiBjYW5jZWxsZWQgZHVlIHRvIGFub3RoZXIgY29uZmxpY3RpbmcgcG9wdXAgYmVpbmcgb3BlbmVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JdOiAnQW4gaW50ZXJuYWwgQXV0aEVycm9yIGhhcyBvY2N1cnJlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQVBQX0NSRURFTlRJQUxdOlxuICAgICAgJ1RoZSBwaG9uZSB2ZXJpZmljYXRpb24gcmVxdWVzdCBjb250YWlucyBhbiBpbnZhbGlkIGFwcGxpY2F0aW9uIHZlcmlmaWVyLicgK1xuICAgICAgJyBUaGUgcmVDQVBUQ0hBIHRva2VuIHJlc3BvbnNlIGlzIGVpdGhlciBpbnZhbGlkIG9yIGV4cGlyZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0FQUF9JRF06XG4gICAgICAnVGhlIG1vYmlsZSBhcHAgaWRlbnRpZmllciBpcyBub3QgcmVnaXN0ZXJlZCBmb3IgdGhlIGN1cnJlbnQgcHJvamVjdC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQVVUSF06XG4gICAgICBcIlRoaXMgdXNlcidzIGNyZWRlbnRpYWwgaXNuJ3QgdmFsaWQgZm9yIHRoaXMgcHJvamVjdC4gVGhpcyBjYW4gaGFwcGVuIFwiICtcbiAgICAgIFwiaWYgdGhlIHVzZXIncyB0b2tlbiBoYXMgYmVlbiB0YW1wZXJlZCB3aXRoLCBvciBpZiB0aGUgdXNlciBpc24ndCBmb3IgXCIgK1xuICAgICAgJ3RoZSBwcm9qZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGlzIEFQSSBrZXkuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0FVVEhfRVZFTlRdOiAnQW4gaW50ZXJuYWwgQXV0aEVycm9yIGhhcyBvY2N1cnJlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09ERV06XG4gICAgICAnVGhlIFNNUyB2ZXJpZmljYXRpb24gY29kZSB1c2VkIHRvIGNyZWF0ZSB0aGUgcGhvbmUgYXV0aCBjcmVkZW50aWFsIGlzICcgK1xuICAgICAgJ2ludmFsaWQuIFBsZWFzZSByZXNlbmQgdGhlIHZlcmlmaWNhdGlvbiBjb2RlIHNtcyBhbmQgYmUgc3VyZSB0byB1c2UgdGhlICcgK1xuICAgICAgJ3ZlcmlmaWNhdGlvbiBjb2RlIHByb3ZpZGVkIGJ5IHRoZSB1c2VyLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9DT05USU5VRV9VUkldOlxuICAgICAgJ1RoZSBjb250aW51ZSBVUkwgcHJvdmlkZWQgaW4gdGhlIHJlcXVlc3QgaXMgaW52YWxpZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09SRE9WQV9DT05GSUdVUkFUSU9OXTpcbiAgICAgICdUaGUgZm9sbG93aW5nIENvcmRvdmEgcGx1Z2lucyBtdXN0IGJlIGluc3RhbGxlZCB0byBlbmFibGUgT0F1dGggc2lnbi1pbjogJyArXG4gICAgICAnY29yZG92YS1wbHVnaW4tYnVpbGRpbmZvLCBjb3Jkb3ZhLXVuaXZlcnNhbC1saW5rcy1wbHVnaW4sICcgK1xuICAgICAgJ2NvcmRvdmEtcGx1Z2luLWJyb3dzZXJ0YWIsIGNvcmRvdmEtcGx1Z2luLWluYXBwYnJvd3NlciBhbmQgJyArXG4gICAgICAnY29yZG92YS1wbHVnaW4tY3VzdG9tdXJsc2NoZW1lLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9DVVNUT01fVE9LRU5dOlxuICAgICAgJ1RoZSBjdXN0b20gdG9rZW4gZm9ybWF0IGlzIGluY29ycmVjdC4gUGxlYXNlIGNoZWNrIHRoZSBkb2N1bWVudGF0aW9uLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9EWU5BTUlDX0xJTktfRE9NQUlOXTpcbiAgICAgICdUaGUgcHJvdmlkZWQgZHluYW1pYyBsaW5rIGRvbWFpbiBpcyBub3QgY29uZmlndXJlZCBvciBhdXRob3JpemVkIGZvciB0aGUgY3VycmVudCBwcm9qZWN0LicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9FTUFJTF06ICdUaGUgZW1haWwgYWRkcmVzcyBpcyBiYWRseSBmb3JtYXR0ZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0VNVUxBVE9SX1NDSEVNRV06XG4gICAgICAnRW11bGF0b3IgVVJMIG11c3Qgc3RhcnQgd2l0aCBhIHZhbGlkIHNjaGVtZSAoaHR0cDovLyBvciBodHRwczovLykuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0FQSV9LRVldOlxuICAgICAgJ1lvdXIgQVBJIGtleSBpcyBpbnZhbGlkLCBwbGVhc2UgY2hlY2sgeW91IGhhdmUgY29waWVkIGl0IGNvcnJlY3RseS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ0VSVF9IQVNIXTpcbiAgICAgICdUaGUgU0hBLTEgY2VydGlmaWNhdGUgaGFzaCBwcm92aWRlZCBpcyBpbnZhbGlkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9DUkVERU5USUFMXTpcbiAgICAgICdUaGUgc3VwcGxpZWQgYXV0aCBjcmVkZW50aWFsIGlzIGluY29ycmVjdCwgbWFsZm9ybWVkIG9yIGhhcyBleHBpcmVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9NRVNTQUdFX1BBWUxPQURdOlxuICAgICAgJ1RoZSBlbWFpbCB0ZW1wbGF0ZSBjb3JyZXNwb25kaW5nIHRvIHRoaXMgYWN0aW9uIGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycyBpbiBpdHMgbWVzc2FnZS4gJyArXG4gICAgICAnUGxlYXNlIGZpeCBieSBnb2luZyB0byB0aGUgQXV0aCBlbWFpbCB0ZW1wbGF0ZXMgc2VjdGlvbiBpbiB0aGUgRmlyZWJhc2UgQ29uc29sZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfTUZBX1NFU1NJT05dOlxuICAgICAgJ1RoZSByZXF1ZXN0IGRvZXMgbm90IGNvbnRhaW4gYSB2YWxpZCBwcm9vZiBvZiBmaXJzdCBmYWN0b3Igc3VjY2Vzc2Z1bCBzaWduLWluLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9PQVVUSF9QUk9WSURFUl06XG4gICAgICAnRW1haWxBdXRoUHJvdmlkZXIgaXMgbm90IHN1cHBvcnRlZCBmb3IgdGhpcyBvcGVyYXRpb24uIFRoaXMgb3BlcmF0aW9uICcgK1xuICAgICAgJ29ubHkgc3VwcG9ydHMgT0F1dGggcHJvdmlkZXJzLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9PQVVUSF9DTElFTlRfSURdOlxuICAgICAgJ1RoZSBPQXV0aCBjbGllbnQgSUQgcHJvdmlkZWQgaXMgZWl0aGVyIGludmFsaWQgb3IgZG9lcyBub3QgbWF0Y2ggdGhlICcgK1xuICAgICAgJ3NwZWNpZmllZCBBUEkga2V5LicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9PUklHSU5dOlxuICAgICAgJ1RoaXMgZG9tYWluIGlzIG5vdCBhdXRob3JpemVkIGZvciBPQXV0aCBvcGVyYXRpb25zIGZvciB5b3VyIEZpcmViYXNlICcgK1xuICAgICAgJ3Byb2plY3QuIEVkaXQgdGhlIGxpc3Qgb2YgYXV0aG9yaXplZCBkb21haW5zIGZyb20gdGhlIEZpcmViYXNlIGNvbnNvbGUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX09PQl9DT0RFXTpcbiAgICAgICdUaGUgYWN0aW9uIGNvZGUgaXMgaW52YWxpZC4gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZSBjb2RlIGlzIG1hbGZvcm1lZCwgJyArXG4gICAgICAnZXhwaXJlZCwgb3IgaGFzIGFscmVhZHkgYmVlbiB1c2VkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9QQVNTV09SRF06XG4gICAgICAnVGhlIHBhc3N3b3JkIGlzIGludmFsaWQgb3IgdGhlIHVzZXIgZG9lcyBub3QgaGF2ZSBhIHBhc3N3b3JkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9QRVJTSVNURU5DRV06XG4gICAgICAnVGhlIHNwZWNpZmllZCBwZXJzaXN0ZW5jZSB0eXBlIGlzIGludmFsaWQuIEl0IGNhbiBvbmx5IGJlIGxvY2FsLCBzZXNzaW9uIG9yIG5vbmUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1BIT05FX05VTUJFUl06XG4gICAgICAnVGhlIGZvcm1hdCBvZiB0aGUgcGhvbmUgbnVtYmVyIHByb3ZpZGVkIGlzIGluY29ycmVjdC4gUGxlYXNlIGVudGVyIHRoZSAnICtcbiAgICAgICdwaG9uZSBudW1iZXIgaW4gYSBmb3JtYXQgdGhhdCBjYW4gYmUgcGFyc2VkIGludG8gRS4xNjQgZm9ybWF0LiBFLjE2NCAnICtcbiAgICAgICdwaG9uZSBudW1iZXJzIGFyZSB3cml0dGVuIGluIHRoZSBmb3JtYXQgWytdW2NvdW50cnkgY29kZV1bc3Vic2NyaWJlciAnICtcbiAgICAgICdudW1iZXIgaW5jbHVkaW5nIGFyZWEgY29kZV0uJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1BST1ZJREVSX0lEXTpcbiAgICAgICdUaGUgc3BlY2lmaWVkIHByb3ZpZGVyIElEIGlzIGludmFsaWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0lQSUVOVF9FTUFJTF06XG4gICAgICAnVGhlIGVtYWlsIGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBhY3Rpb24gZmFpbGVkIHRvIHNlbmQgYXMgdGhlIHByb3ZpZGVkICcgK1xuICAgICAgJ3JlY2lwaWVudCBlbWFpbCBhZGRyZXNzIGlzIGludmFsaWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1NFTkRFUl06XG4gICAgICAnVGhlIGVtYWlsIHRlbXBsYXRlIGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBhY3Rpb24gY29udGFpbnMgYW4gaW52YWxpZCBzZW5kZXIgZW1haWwgb3IgbmFtZS4gJyArXG4gICAgICAnUGxlYXNlIGZpeCBieSBnb2luZyB0byB0aGUgQXV0aCBlbWFpbCB0ZW1wbGF0ZXMgc2VjdGlvbiBpbiB0aGUgRmlyZWJhc2UgQ29uc29sZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfU0VTU0lPTl9JTkZPXTpcbiAgICAgICdUaGUgdmVyaWZpY2F0aW9uIElEIHVzZWQgdG8gY3JlYXRlIHRoZSBwaG9uZSBhdXRoIGNyZWRlbnRpYWwgaXMgaW52YWxpZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfVEVOQU5UX0lEXTpcbiAgICAgIFwiVGhlIEF1dGggaW5zdGFuY2UncyB0ZW5hbnQgSUQgaXMgaW52YWxpZC5cIixcbiAgICBbQXV0aEVycm9yQ29kZS5MT0dJTl9CTE9DS0VEXTpcbiAgICAgICdMb2dpbiBibG9ja2VkIGJ5IHVzZXItcHJvdmlkZWQgbWV0aG9kOiB7JG9yaWdpbmFsTWVzc2FnZX0nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQU5EUk9JRF9QQUNLQUdFX05BTUVdOlxuICAgICAgJ0FuIEFuZHJvaWQgUGFja2FnZSBOYW1lIG11c3QgYmUgcHJvdmlkZWQgaWYgdGhlIEFuZHJvaWQgQXBwIGlzIHJlcXVpcmVkIHRvIGJlIGluc3RhbGxlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQVVUSF9ET01BSU5dOlxuICAgICAgJ0JlIHN1cmUgdG8gaW5jbHVkZSBhdXRoRG9tYWluIHdoZW4gY2FsbGluZyBmaXJlYmFzZS5pbml0aWFsaXplQXBwKCksICcgK1xuICAgICAgJ2J5IGZvbGxvd2luZyB0aGUgaW5zdHJ1Y3Rpb25zIGluIHRoZSBGaXJlYmFzZSBjb25zb2xlLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19BUFBfQ1JFREVOVElBTF06XG4gICAgICAnVGhlIHBob25lIHZlcmlmaWNhdGlvbiByZXF1ZXN0IGlzIG1pc3NpbmcgYW4gYXBwbGljYXRpb24gdmVyaWZpZXIgJyArXG4gICAgICAnYXNzZXJ0aW9uLiBBIHJlQ0FQVENIQSByZXNwb25zZSB0b2tlbiBuZWVkcyB0byBiZSBwcm92aWRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQ09ERV06XG4gICAgICAnVGhlIHBob25lIGF1dGggY3JlZGVudGlhbCB3YXMgY3JlYXRlZCB3aXRoIGFuIGVtcHR5IFNNUyB2ZXJpZmljYXRpb24gY29kZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQ09OVElOVUVfVVJJXTpcbiAgICAgICdBIGNvbnRpbnVlIFVSTCBtdXN0IGJlIHByb3ZpZGVkIGluIHRoZSByZXF1ZXN0LicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19JRlJBTUVfU1RBUlRdOiAnQW4gaW50ZXJuYWwgQXV0aEVycm9yIGhhcyBvY2N1cnJlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfSU9TX0JVTkRMRV9JRF06XG4gICAgICAnQW4gaU9TIEJ1bmRsZSBJRCBtdXN0IGJlIHByb3ZpZGVkIGlmIGFuIEFwcCBTdG9yZSBJRCBpcyBwcm92aWRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfT1JfSU5WQUxJRF9OT05DRV06XG4gICAgICAnVGhlIHJlcXVlc3QgZG9lcyBub3QgY29udGFpbiBhIHZhbGlkIG5vbmNlLiBUaGlzIGNhbiBvY2N1ciBpZiB0aGUgJyArXG4gICAgICAnU0hBLTI1NiBoYXNoIG9mIHRoZSBwcm92aWRlZCByYXcgbm9uY2UgZG9lcyBub3QgbWF0Y2ggdGhlIGhhc2hlZCBub25jZSAnICtcbiAgICAgICdpbiB0aGUgSUQgdG9rZW4gcGF5bG9hZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfUEFTU1dPUkRdOiAnQSBub24tZW1wdHkgcGFzc3dvcmQgbXVzdCBiZSBwcm92aWRlZCcsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19NRkFfSU5GT106XG4gICAgICAnTm8gc2Vjb25kIGZhY3RvciBpZGVudGlmaWVyIGlzIHByb3ZpZGVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19NRkFfU0VTU0lPTl06XG4gICAgICAnVGhlIHJlcXVlc3QgaXMgbWlzc2luZyBwcm9vZiBvZiBmaXJzdCBmYWN0b3Igc3VjY2Vzc2Z1bCBzaWduLWluLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19QSE9ORV9OVU1CRVJdOlxuICAgICAgJ1RvIHNlbmQgdmVyaWZpY2F0aW9uIGNvZGVzLCBwcm92aWRlIGEgcGhvbmUgbnVtYmVyIGZvciB0aGUgcmVjaXBpZW50LicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19TRVNTSU9OX0lORk9dOlxuICAgICAgJ1RoZSBwaG9uZSBhdXRoIGNyZWRlbnRpYWwgd2FzIGNyZWF0ZWQgd2l0aCBhbiBlbXB0eSB2ZXJpZmljYXRpb24gSUQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5NT0RVTEVfREVTVFJPWUVEXTpcbiAgICAgICdUaGlzIGluc3RhbmNlIG9mIEZpcmViYXNlQXBwIGhhcyBiZWVuIGRlbGV0ZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5NRkFfSU5GT19OT1RfRk9VTkRdOlxuICAgICAgJ1RoZSB1c2VyIGRvZXMgbm90IGhhdmUgYSBzZWNvbmQgZmFjdG9yIG1hdGNoaW5nIHRoZSBpZGVudGlmaWVyIHByb3ZpZGVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVEXTpcbiAgICAgICdQcm9vZiBvZiBvd25lcnNoaXAgb2YgYSBzZWNvbmQgZmFjdG9yIGlzIHJlcXVpcmVkIHRvIGNvbXBsZXRlIHNpZ24taW4uJyxcbiAgICBbQXV0aEVycm9yQ29kZS5ORUVEX0NPTkZJUk1BVElPTl06XG4gICAgICAnQW4gYWNjb3VudCBhbHJlYWR5IGV4aXN0cyB3aXRoIHRoZSBzYW1lIGVtYWlsIGFkZHJlc3MgYnV0IGRpZmZlcmVudCAnICtcbiAgICAgICdzaWduLWluIGNyZWRlbnRpYWxzLiBTaWduIGluIHVzaW5nIGEgcHJvdmlkZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgJyArXG4gICAgICAnZW1haWwgYWRkcmVzcy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk5FVFdPUktfUkVRVUVTVF9GQUlMRURdOlxuICAgICAgJ0EgbmV0d29yayBBdXRoRXJyb3IgKHN1Y2ggYXMgdGltZW91dCwgaW50ZXJydXB0ZWQgY29ubmVjdGlvbiBvciB1bnJlYWNoYWJsZSBob3N0KSBoYXMgb2NjdXJyZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5OT19BVVRIX0VWRU5UXTogJ0FuIGludGVybmFsIEF1dGhFcnJvciBoYXMgb2NjdXJyZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5OT19TVUNIX1BST1ZJREVSXTpcbiAgICAgICdVc2VyIHdhcyBub3QgbGlua2VkIHRvIGFuIGFjY291bnQgd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXIuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5OVUxMX1VTRVJdOlxuICAgICAgJ0EgbnVsbCB1c2VyIG9iamVjdCB3YXMgcHJvdmlkZWQgYXMgdGhlIGFyZ3VtZW50IGZvciBhbiBvcGVyYXRpb24gd2hpY2ggJyArXG4gICAgICAncmVxdWlyZXMgYSBub24tbnVsbCB1c2VyIG9iamVjdC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk9QRVJBVElPTl9OT1RfQUxMT1dFRF06XG4gICAgICAnVGhlIGdpdmVuIHNpZ24taW4gcHJvdmlkZXIgaXMgZGlzYWJsZWQgZm9yIHRoaXMgRmlyZWJhc2UgcHJvamVjdC4gJyArXG4gICAgICAnRW5hYmxlIGl0IGluIHRoZSBGaXJlYmFzZSBjb25zb2xlLCB1bmRlciB0aGUgc2lnbi1pbiBtZXRob2QgdGFiIG9mIHRoZSAnICtcbiAgICAgICdBdXRoIHNlY3Rpb24uJyxcbiAgICBbQXV0aEVycm9yQ29kZS5PUEVSQVRJT05fTk9UX1NVUFBPUlRFRF06XG4gICAgICAnVGhpcyBvcGVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgZW52aXJvbm1lbnQgdGhpcyBhcHBsaWNhdGlvbiBpcyAnICtcbiAgICAgICdydW5uaW5nIG9uLiBcImxvY2F0aW9uLnByb3RvY29sXCIgbXVzdCBiZSBodHRwLCBodHRwcyBvciBjaHJvbWUtZXh0ZW5zaW9uJyArXG4gICAgICAnIGFuZCB3ZWIgc3RvcmFnZSBtdXN0IGJlIGVuYWJsZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5QT1BVUF9CTE9DS0VEXTpcbiAgICAgICdVbmFibGUgdG8gZXN0YWJsaXNoIGEgY29ubmVjdGlvbiB3aXRoIHRoZSBwb3B1cC4gSXQgbWF5IGhhdmUgYmVlbiBibG9ja2VkIGJ5IHRoZSBicm93c2VyLicsXG4gICAgW0F1dGhFcnJvckNvZGUuUE9QVVBfQ0xPU0VEX0JZX1VTRVJdOlxuICAgICAgJ1RoZSBwb3B1cCBoYXMgYmVlbiBjbG9zZWQgYnkgdGhlIHVzZXIgYmVmb3JlIGZpbmFsaXppbmcgdGhlIG9wZXJhdGlvbi4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlBST1ZJREVSX0FMUkVBRFlfTElOS0VEXTpcbiAgICAgICdVc2VyIGNhbiBvbmx5IGJlIGxpbmtlZCB0byBvbmUgaWRlbnRpdHkgZm9yIHRoZSBnaXZlbiBwcm92aWRlci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVEXTpcbiAgICAgIFwiVGhlIHByb2plY3QncyBxdW90YSBmb3IgdGhpcyBvcGVyYXRpb24gaGFzIGJlZW4gZXhjZWVkZWQuXCIsXG4gICAgW0F1dGhFcnJvckNvZGUuUkVESVJFQ1RfQ0FOQ0VMTEVEX0JZX1VTRVJdOlxuICAgICAgJ1RoZSByZWRpcmVjdCBvcGVyYXRpb24gaGFzIGJlZW4gY2FuY2VsbGVkIGJ5IHRoZSB1c2VyIGJlZm9yZSBmaW5hbGl6aW5nLicsXG4gICAgW0F1dGhFcnJvckNvZGUuUkVESVJFQ1RfT1BFUkFUSU9OX1BFTkRJTkddOlxuICAgICAgJ0EgcmVkaXJlY3Qgc2lnbi1pbiBvcGVyYXRpb24gaXMgYWxyZWFkeSBwZW5kaW5nLicsXG4gICAgW0F1dGhFcnJvckNvZGUuUkVKRUNURURfQ1JFREVOVElBTF06XG4gICAgICAnVGhlIHJlcXVlc3QgY29udGFpbnMgbWFsZm9ybWVkIG9yIG1pc21hdGNoaW5nIGNyZWRlbnRpYWxzLicsXG4gICAgW0F1dGhFcnJvckNvZGUuU0VDT05EX0ZBQ1RPUl9BTFJFQURZX0VOUk9MTEVEXTpcbiAgICAgICdUaGUgc2Vjb25kIGZhY3RvciBpcyBhbHJlYWR5IGVucm9sbGVkIG9uIHRoaXMgYWNjb3VudC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlNFQ09ORF9GQUNUT1JfTElNSVRfRVhDRUVERURdOlxuICAgICAgJ1RoZSBtYXhpbXVtIGFsbG93ZWQgbnVtYmVyIG9mIHNlY29uZCBmYWN0b3JzIG9uIGEgdXNlciBoYXMgYmVlbiBleGNlZWRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlRFTkFOVF9JRF9NSVNNQVRDSF06XG4gICAgICBcIlRoZSBwcm92aWRlZCB0ZW5hbnQgSUQgZG9lcyBub3QgbWF0Y2ggdGhlIEF1dGggaW5zdGFuY2UncyB0ZW5hbnQgSURcIixcbiAgICBbQXV0aEVycm9yQ29kZS5USU1FT1VUXTogJ1RoZSBvcGVyYXRpb24gaGFzIHRpbWVkIG91dC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlRPS0VOX0VYUElSRURdOlxuICAgICAgXCJUaGUgdXNlcidzIGNyZWRlbnRpYWwgaXMgbm8gbG9uZ2VyIHZhbGlkLiBUaGUgdXNlciBtdXN0IHNpZ24gaW4gYWdhaW4uXCIsXG4gICAgW0F1dGhFcnJvckNvZGUuVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSXTpcbiAgICAgICdXZSBoYXZlIGJsb2NrZWQgYWxsIHJlcXVlc3RzIGZyb20gdGhpcyBkZXZpY2UgZHVlIHRvIHVudXN1YWwgYWN0aXZpdHkuICcgK1xuICAgICAgJ1RyeSBhZ2FpbiBsYXRlci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOQVVUSE9SSVpFRF9ET01BSU5dOlxuICAgICAgJ1RoZSBkb21haW4gb2YgdGhlIGNvbnRpbnVlIFVSTCBpcyBub3Qgd2hpdGVsaXN0ZWQuICBQbGVhc2Ugd2hpdGVsaXN0ICcgK1xuICAgICAgJ3RoZSBkb21haW4gaW4gdGhlIEZpcmViYXNlIGNvbnNvbGUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5VTlNVUFBPUlRFRF9GSVJTVF9GQUNUT1JdOlxuICAgICAgJ0Vucm9sbGluZyBhIHNlY29uZCBmYWN0b3Igb3Igc2lnbmluZyBpbiB3aXRoIGEgbXVsdGktZmFjdG9yIGFjY291bnQgcmVxdWlyZXMgc2lnbi1pbiB3aXRoIGEgc3VwcG9ydGVkIGZpcnN0IGZhY3Rvci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOU1VQUE9SVEVEX1BFUlNJU1RFTkNFXTpcbiAgICAgICdUaGUgY3VycmVudCBlbnZpcm9ubWVudCBkb2VzIG5vdCBzdXBwb3J0IHRoZSBzcGVjaWZpZWQgcGVyc2lzdGVuY2UgdHlwZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOU1VQUE9SVEVEX1RFTkFOVF9PUEVSQVRJT05dOlxuICAgICAgJ1RoaXMgb3BlcmF0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgaW4gYSBtdWx0aS10ZW5hbnQgY29udGV4dC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOVkVSSUZJRURfRU1BSUxdOlxuICAgICAgJ1RoZSBvcGVyYXRpb24gcmVxdWlyZXMgYSB2ZXJpZmllZCBlbWFpbC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfQ0FOQ0VMTEVEXTpcbiAgICAgICdUaGUgdXNlciBkaWQgbm90IGdyYW50IHlvdXIgYXBwbGljYXRpb24gdGhlIHBlcm1pc3Npb25zIGl0IHJlcXVlc3RlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfREVMRVRFRF06XG4gICAgICAnVGhlcmUgaXMgbm8gdXNlciByZWNvcmQgY29ycmVzcG9uZGluZyB0byB0aGlzIGlkZW50aWZpZXIuIFRoZSB1c2VyIG1heSAnICtcbiAgICAgICdoYXZlIGJlZW4gZGVsZXRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfRElTQUJMRURdOlxuICAgICAgJ1RoZSB1c2VyIGFjY291bnQgaGFzIGJlZW4gZGlzYWJsZWQgYnkgYW4gYWRtaW5pc3RyYXRvci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfTUlTTUFUQ0hdOlxuICAgICAgJ1RoZSBzdXBwbGllZCBjcmVkZW50aWFscyBkbyBub3QgY29ycmVzcG9uZCB0byB0aGUgcHJldmlvdXNseSBzaWduZWQgaW4gdXNlci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfU0lHTkVEX09VVF06ICcnLFxuICAgIFtBdXRoRXJyb3JDb2RlLldFQUtfUEFTU1dPUkRdOlxuICAgICAgJ1RoZSBwYXNzd29yZCBtdXN0IGJlIDYgY2hhcmFjdGVycyBsb25nIG9yIG1vcmUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5XRUJfU1RPUkFHRV9VTlNVUFBPUlRFRF06XG4gICAgICAnVGhpcyBicm93c2VyIGlzIG5vdCBzdXBwb3J0ZWQgb3IgM3JkIHBhcnR5IGNvb2tpZXMgYW5kIGRhdGEgbWF5IGJlIGRpc2FibGVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuQUxSRUFEWV9JTklUSUFMSVpFRF06XG4gICAgICAnaW5pdGlhbGl6ZUF1dGgoKSBoYXMgYWxyZWFkeSBiZWVuIGNhbGxlZCB3aXRoICcgK1xuICAgICAgJ2RpZmZlcmVudCBvcHRpb25zLiBUbyBhdm9pZCB0aGlzIGVycm9yLCBjYWxsIGluaXRpYWxpemVBdXRoKCkgd2l0aCB0aGUgJyArXG4gICAgICAnc2FtZSBvcHRpb25zIGFzIHdoZW4gaXQgd2FzIG9yaWdpbmFsbHkgY2FsbGVkLCBvciBjYWxsIGdldEF1dGgoKSB0byByZXR1cm4gdGhlJyArXG4gICAgICAnIGFscmVhZHkgaW5pdGlhbGl6ZWQgaW5zdGFuY2UuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5NSVNTSU5HX1JFQ0FQVENIQV9UT0tFTl06XG4gICAgICAnVGhlIHJlQ0FQVENIQSB0b2tlbiBpcyBtaXNzaW5nIHdoZW4gc2VuZGluZyByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9SRUNBUFRDSEFfVE9LRU5dOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgdG9rZW4gaXMgaW52YWxpZCB3aGVuIHNlbmRpbmcgcmVxdWVzdCB0byB0aGUgYmFja2VuZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfUkVDQVBUQ0hBX0FDVElPTl06XG4gICAgICAnVGhlIHJlQ0FQVENIQSBhY3Rpb24gaXMgaW52YWxpZCB3aGVuIHNlbmRpbmcgcmVxdWVzdCB0byB0aGUgYmFja2VuZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlJFQ0FQVENIQV9OT1RfRU5BQkxFRF06XG4gICAgICAncmVDQVBUQ0hBIEVudGVycHJpc2UgaW50ZWdyYXRpb24gaXMgbm90IGVuYWJsZWQgZm9yIHRoaXMgcHJvamVjdC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQ0xJRU5UX1RZUEVdOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgY2xpZW50IHR5cGUgaXMgbWlzc2luZyB3aGVuIHNlbmRpbmcgcmVxdWVzdCB0byB0aGUgYmFja2VuZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT05dOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgdmVyc2lvbiBpcyBtaXNzaW5nIHdoZW4gc2VuZGluZyByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9SRVFfVFlQRV06ICdJbnZhbGlkIHJlcXVlc3QgcGFyYW1ldGVycy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfUkVDQVBUQ0hBX1ZFUlNJT05dOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgdmVyc2lvbiBpcyBpbnZhbGlkIHdoZW4gc2VuZGluZyByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kLicsXG4gICAgW0F1dGhFcnJvckNvZGUuVU5TVVBQT1JURURfUEFTU1dPUkRfUE9MSUNZX1NDSEVNQV9WRVJTSU9OXTpcbiAgICAgICdUaGUgcGFzc3dvcmQgcG9saWN5IHJlY2VpdmVkIGZyb20gdGhlIGJhY2tlbmQgdXNlcyBhIHNjaGVtYSB2ZXJzaW9uIHRoYXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGlzIHZlcnNpb24gb2YgdGhlIEZpcmViYXNlIFNESy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlBBU1NXT1JEX0RPRVNfTk9UX01FRVRfUkVRVUlSRU1FTlRTXTpcbiAgICAgICdUaGUgcGFzc3dvcmQgZG9lcyBub3QgbWVldCB0aGUgcmVxdWlyZW1lbnRzLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9IT1NUSU5HX0xJTktfRE9NQUlOXTpcbiAgICAgICdUaGUgcHJvdmlkZWQgSG9zdGluZyBsaW5rIGRvbWFpbiBpcyBub3QgY29uZmlndXJlZCBpbiBGaXJlYmFzZSBIb3N0aW5nIG9yIGlzIG5vdCBvd25lZCBieSAnICtcbiAgICAgICd0aGUgY3VycmVudCBwcm9qZWN0LiBUaGlzIGNhbm5vdCBiZSBhIGRlZmF1bHQgSG9zdGluZyBkb21haW4gKGB3ZWIuYXBwYCBvciBgZmlyZWJhc2VhcHAuY29tYCkuJ1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVycm9yTWFwUmV0cmlldmVyIGV4dGVuZHMgQXV0aEVycm9yTWFwIHtcbiAgKCk6IEVycm9yTWFwPEF1dGhFcnJvckNvZGU+O1xufVxuXG5mdW5jdGlvbiBfcHJvZEVycm9yTWFwKCk6IEVycm9yTWFwPEF1dGhFcnJvckNvZGU+IHtcbiAgLy8gV2Ugd2lsbCBpbmNsdWRlIHRoaXMgb25lIG1lc3NhZ2UgaW4gdGhlIHByb2QgZXJyb3IgbWFwIHNpbmNlIGJ5IHRoZSB2ZXJ5XG4gIC8vIG5hdHVyZSBvZiB0aGlzIGVycm9yLCBkZXZlbG9wZXJzIHdpbGwgbmV2ZXIgYmUgYWJsZSB0byBzZWUgdGhlIG1lc3NhZ2VcbiAgLy8gdXNpbmcgdGhlIGRlYnVnRXJyb3JNYXAgKHdoaWNoIGlzIGluc3RhbGxlZCBkdXJpbmcgYXV0aCBpbml0aWFsaXphdGlvbikuXG4gIHJldHVybiB7XG4gICAgW0F1dGhFcnJvckNvZGUuREVQRU5ERU5UX1NES19JTklUX0JFRk9SRV9BVVRIXTpcbiAgICAgICdBbm90aGVyIEZpcmViYXNlIFNESyB3YXMgaW5pdGlhbGl6ZWQgYW5kIGlzIHRyeWluZyB0byB1c2UgQXV0aCBiZWZvcmUgQXV0aCBpcyAnICtcbiAgICAgICdpbml0aWFsaXplZC4gUGxlYXNlIGJlIHN1cmUgdG8gY2FsbCBgaW5pdGlhbGl6ZUF1dGhgIG9yIGBnZXRBdXRoYCBiZWZvcmUgJyArXG4gICAgICAnc3RhcnRpbmcgYW55IG90aGVyIEZpcmViYXNlIFNESy4nXG4gIH0gYXMgRXJyb3JNYXA8QXV0aEVycm9yQ29kZT47XG59XG5cbi8qKlxuICogQSB2ZXJib3NlIGVycm9yIG1hcCB3aXRoIGRldGFpbGVkIGRlc2NyaXB0aW9ucyBmb3IgbW9zdCBlcnJvciBjb2Rlcy5cbiAqXG4gKiBTZWUgZGlzY3Vzc2lvbiBhdCB7QGxpbmsgQXV0aEVycm9yTWFwfVxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGRlYnVnRXJyb3JNYXA6IEF1dGhFcnJvck1hcCA9IF9kZWJ1Z0Vycm9yTWFwO1xuXG4vKipcbiAqIEEgbWluaW1hbCBlcnJvciBtYXAgd2l0aCBhbGwgdmVyYm9zZSBlcnJvciBtZXNzYWdlcyBzdHJpcHBlZC5cbiAqXG4gKiBTZWUgZGlzY3Vzc2lvbiBhdCB7QGxpbmsgQXV0aEVycm9yTWFwfVxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHByb2RFcnJvck1hcDogQXV0aEVycm9yTWFwID0gX3Byb2RFcnJvck1hcDtcblxuZXhwb3J0IGludGVyZmFjZSBOYW1lZEVycm9yUGFyYW1zIHtcbiAgYXBwTmFtZTogQXBwTmFtZTtcbiAgY3JlZGVudGlhbD86IEF1dGhDcmVkZW50aWFsO1xuICBlbWFpbD86IHN0cmluZztcbiAgcGhvbmVOdW1iZXI/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICB1c2VyPzogVXNlcjtcbiAgX3NlcnZlclJlc3BvbnNlPzogb2JqZWN0O1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG50eXBlIEdlbmVyaWNBdXRoRXJyb3JQYXJhbXMgPSB7XG4gIFtrZXkgaW4gRXhjbHVkZTxcbiAgICBBdXRoRXJyb3JDb2RlLFxuICAgIHwgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUlxuICAgIHwgQXV0aEVycm9yQ29kZS5ERVBFTkRFTlRfU0RLX0lOSVRfQkVGT1JFX0FVVEhcbiAgICB8IEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JcbiAgICB8IEF1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVEXG4gICAgfCBBdXRoRXJyb3JDb2RlLk5PX0FVVEhfRVZFTlRcbiAgICB8IEF1dGhFcnJvckNvZGUuT1BFUkFUSU9OX05PVF9TVVBQT1JURURcbiAgPl06IHtcbiAgICBhcHBOYW1lPzogQXBwTmFtZTtcbiAgICBlbWFpbD86IHN0cmluZztcbiAgICBwaG9uZU51bWJlcj86IHN0cmluZztcbiAgICBtZXNzYWdlPzogc3RyaW5nO1xuICB9O1xufTtcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRoRXJyb3JQYXJhbXMgZXh0ZW5kcyBHZW5lcmljQXV0aEVycm9yUGFyYW1zIHtcbiAgW0F1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JdOiB7IGFwcE5hbWU/OiBBcHBOYW1lIH07XG4gIFtBdXRoRXJyb3JDb2RlLkRFUEVOREVOVF9TREtfSU5JVF9CRUZPUkVfQVVUSF06IHsgYXBwTmFtZT86IEFwcE5hbWUgfTtcbiAgW0F1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JdOiB7IGFwcE5hbWU/OiBBcHBOYW1lIH07XG4gIFtBdXRoRXJyb3JDb2RlLkxPR0lOX0JMT0NLRURdOiB7XG4gICAgYXBwTmFtZT86IEFwcE5hbWU7XG4gICAgb3JpZ2luYWxNZXNzYWdlPzogc3RyaW5nO1xuICB9O1xuICBbQXV0aEVycm9yQ29kZS5PUEVSQVRJT05fTk9UX1NVUFBPUlRFRF06IHsgYXBwTmFtZT86IEFwcE5hbWUgfTtcbiAgW0F1dGhFcnJvckNvZGUuTk9fQVVUSF9FVkVOVF06IHsgYXBwTmFtZT86IEFwcE5hbWUgfTtcbiAgW0F1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVEXToge1xuICAgIGFwcE5hbWU6IEFwcE5hbWU7XG4gICAgX3NlcnZlclJlc3BvbnNlOiBJZFRva2VuTWZhUmVzcG9uc2U7XG4gIH07XG4gIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09SRE9WQV9DT05GSUdVUkFUSU9OXToge1xuICAgIGFwcE5hbWU6IEFwcE5hbWU7XG4gICAgbWlzc2luZ1BsdWdpbj86IHN0cmluZztcbiAgfTtcbn1cblxuZXhwb3J0IGNvbnN0IF9ERUZBVUxUX0FVVEhfRVJST1JfRkFDVE9SWSA9IG5ldyBFcnJvckZhY3Rvcnk8XG4gIEF1dGhFcnJvckNvZGUsXG4gIEF1dGhFcnJvclBhcmFtc1xuPignYXV0aCcsICdGaXJlYmFzZScsIF9wcm9kRXJyb3JNYXAoKSk7XG5cbi8qKlxuICogQSBtYXAgb2YgcG90ZW50aWFsIGBBdXRoYCBlcnJvciBjb2RlcywgZm9yIGVhc2llciBjb21wYXJpc29uIHdpdGggZXJyb3JzXG4gKiB0aHJvd24gYnkgdGhlIFNESy5cbiAqXG4gKiBAcmVtYXJrc1xuICogTm90ZSB0aGF0IHlvdSBjYW4ndCB0cmVlLXNoYWtlIGluZGl2aWR1YWwga2V5c1xuICogaW4gdGhlIG1hcCwgc28gYnkgdXNpbmcgdGhlIG1hcCB5b3UgbWlnaHQgc3Vic3RhbnRpYWxseSBpbmNyZWFzZSB5b3VyXG4gKiBidW5kbGUgc2l6ZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBBVVRIX0VSUk9SX0NPREVTX01BUF9ET19OT1RfVVNFX0lOVEVSTkFMTFkgPSB7XG4gIEFETUlOX09OTFlfT1BFUkFUSU9OOiAnYXV0aC9hZG1pbi1yZXN0cmljdGVkLW9wZXJhdGlvbicsXG4gIEFSR1VNRU5UX0VSUk9SOiAnYXV0aC9hcmd1bWVudC1lcnJvcicsXG4gIEFQUF9OT1RfQVVUSE9SSVpFRDogJ2F1dGgvYXBwLW5vdC1hdXRob3JpemVkJyxcbiAgQVBQX05PVF9JTlNUQUxMRUQ6ICdhdXRoL2FwcC1ub3QtaW5zdGFsbGVkJyxcbiAgQ0FQVENIQV9DSEVDS19GQUlMRUQ6ICdhdXRoL2NhcHRjaGEtY2hlY2stZmFpbGVkJyxcbiAgQ09ERV9FWFBJUkVEOiAnYXV0aC9jb2RlLWV4cGlyZWQnLFxuICBDT1JET1ZBX05PVF9SRUFEWTogJ2F1dGgvY29yZG92YS1ub3QtcmVhZHknLFxuICBDT1JTX1VOU1VQUE9SVEVEOiAnYXV0aC9jb3JzLXVuc3VwcG9ydGVkJyxcbiAgQ1JFREVOVElBTF9BTFJFQURZX0lOX1VTRTogJ2F1dGgvY3JlZGVudGlhbC1hbHJlYWR5LWluLXVzZScsXG4gIENSRURFTlRJQUxfTUlTTUFUQ0g6ICdhdXRoL2N1c3RvbS10b2tlbi1taXNtYXRjaCcsXG4gIENSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTjogJ2F1dGgvcmVxdWlyZXMtcmVjZW50LWxvZ2luJyxcbiAgREVQRU5ERU5UX1NES19JTklUX0JFRk9SRV9BVVRIOiAnYXV0aC9kZXBlbmRlbnQtc2RrLWluaXRpYWxpemVkLWJlZm9yZS1hdXRoJyxcbiAgRFlOQU1JQ19MSU5LX05PVF9BQ1RJVkFURUQ6ICdhdXRoL2R5bmFtaWMtbGluay1ub3QtYWN0aXZhdGVkJyxcbiAgRU1BSUxfQ0hBTkdFX05FRURTX1ZFUklGSUNBVElPTjogJ2F1dGgvZW1haWwtY2hhbmdlLW5lZWRzLXZlcmlmaWNhdGlvbicsXG4gIEVNQUlMX0VYSVNUUzogJ2F1dGgvZW1haWwtYWxyZWFkeS1pbi11c2UnLFxuICBFTVVMQVRPUl9DT05GSUdfRkFJTEVEOiAnYXV0aC9lbXVsYXRvci1jb25maWctZmFpbGVkJyxcbiAgRVhQSVJFRF9PT0JfQ09ERTogJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZScsXG4gIEVYUElSRURfUE9QVVBfUkVRVUVTVDogJ2F1dGgvY2FuY2VsbGVkLXBvcHVwLXJlcXVlc3QnLFxuICBJTlRFUk5BTF9FUlJPUjogJ2F1dGgvaW50ZXJuYWwtZXJyb3InLFxuICBJTlZBTElEX0FQSV9LRVk6ICdhdXRoL2ludmFsaWQtYXBpLWtleScsXG4gIElOVkFMSURfQVBQX0NSRURFTlRJQUw6ICdhdXRoL2ludmFsaWQtYXBwLWNyZWRlbnRpYWwnLFxuICBJTlZBTElEX0FQUF9JRDogJ2F1dGgvaW52YWxpZC1hcHAtaWQnLFxuICBJTlZBTElEX0FVVEg6ICdhdXRoL2ludmFsaWQtdXNlci10b2tlbicsXG4gIElOVkFMSURfQVVUSF9FVkVOVDogJ2F1dGgvaW52YWxpZC1hdXRoLWV2ZW50JyxcbiAgSU5WQUxJRF9DRVJUX0hBU0g6ICdhdXRoL2ludmFsaWQtY2VydC1oYXNoJyxcbiAgSU5WQUxJRF9DT0RFOiAnYXV0aC9pbnZhbGlkLXZlcmlmaWNhdGlvbi1jb2RlJyxcbiAgSU5WQUxJRF9DT05USU5VRV9VUkk6ICdhdXRoL2ludmFsaWQtY29udGludWUtdXJpJyxcbiAgSU5WQUxJRF9DT1JET1ZBX0NPTkZJR1VSQVRJT046ICdhdXRoL2ludmFsaWQtY29yZG92YS1jb25maWd1cmF0aW9uJyxcbiAgSU5WQUxJRF9DVVNUT01fVE9LRU46ICdhdXRoL2ludmFsaWQtY3VzdG9tLXRva2VuJyxcbiAgSU5WQUxJRF9EWU5BTUlDX0xJTktfRE9NQUlOOiAnYXV0aC9pbnZhbGlkLWR5bmFtaWMtbGluay1kb21haW4nLFxuICBJTlZBTElEX0VNQUlMOiAnYXV0aC9pbnZhbGlkLWVtYWlsJyxcbiAgSU5WQUxJRF9FTVVMQVRPUl9TQ0hFTUU6ICdhdXRoL2ludmFsaWQtZW11bGF0b3Itc2NoZW1lJyxcbiAgSU5WQUxJRF9JRFBfUkVTUE9OU0U6ICdhdXRoL2ludmFsaWQtY3JlZGVudGlhbCcsXG4gIElOVkFMSURfTE9HSU5fQ1JFREVOVElBTFM6ICdhdXRoL2ludmFsaWQtY3JlZGVudGlhbCcsXG4gIElOVkFMSURfTUVTU0FHRV9QQVlMT0FEOiAnYXV0aC9pbnZhbGlkLW1lc3NhZ2UtcGF5bG9hZCcsXG4gIElOVkFMSURfTUZBX1NFU1NJT046ICdhdXRoL2ludmFsaWQtbXVsdGktZmFjdG9yLXNlc3Npb24nLFxuICBJTlZBTElEX09BVVRIX0NMSUVOVF9JRDogJ2F1dGgvaW52YWxpZC1vYXV0aC1jbGllbnQtaWQnLFxuICBJTlZBTElEX09BVVRIX1BST1ZJREVSOiAnYXV0aC9pbnZhbGlkLW9hdXRoLXByb3ZpZGVyJyxcbiAgSU5WQUxJRF9PT0JfQ09ERTogJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZScsXG4gIElOVkFMSURfT1JJR0lOOiAnYXV0aC91bmF1dGhvcml6ZWQtZG9tYWluJyxcbiAgSU5WQUxJRF9QQVNTV09SRDogJ2F1dGgvd3JvbmctcGFzc3dvcmQnLFxuICBJTlZBTElEX1BFUlNJU1RFTkNFOiAnYXV0aC9pbnZhbGlkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBJTlZBTElEX1BIT05FX05VTUJFUjogJ2F1dGgvaW52YWxpZC1waG9uZS1udW1iZXInLFxuICBJTlZBTElEX1BST1ZJREVSX0lEOiAnYXV0aC9pbnZhbGlkLXByb3ZpZGVyLWlkJyxcbiAgSU5WQUxJRF9SRUNJUElFTlRfRU1BSUw6ICdhdXRoL2ludmFsaWQtcmVjaXBpZW50LWVtYWlsJyxcbiAgSU5WQUxJRF9TRU5ERVI6ICdhdXRoL2ludmFsaWQtc2VuZGVyJyxcbiAgSU5WQUxJRF9TRVNTSU9OX0lORk86ICdhdXRoL2ludmFsaWQtdmVyaWZpY2F0aW9uLWlkJyxcbiAgSU5WQUxJRF9URU5BTlRfSUQ6ICdhdXRoL2ludmFsaWQtdGVuYW50LWlkJyxcbiAgTUZBX0lORk9fTk9UX0ZPVU5EOiAnYXV0aC9tdWx0aS1mYWN0b3ItaW5mby1ub3QtZm91bmQnLFxuICBNRkFfUkVRVUlSRUQ6ICdhdXRoL211bHRpLWZhY3Rvci1hdXRoLXJlcXVpcmVkJyxcbiAgTUlTU0lOR19BTkRST0lEX1BBQ0tBR0VfTkFNRTogJ2F1dGgvbWlzc2luZy1hbmRyb2lkLXBrZy1uYW1lJyxcbiAgTUlTU0lOR19BUFBfQ1JFREVOVElBTDogJ2F1dGgvbWlzc2luZy1hcHAtY3JlZGVudGlhbCcsXG4gIE1JU1NJTkdfQVVUSF9ET01BSU46ICdhdXRoL2F1dGgtZG9tYWluLWNvbmZpZy1yZXF1aXJlZCcsXG4gIE1JU1NJTkdfQ09ERTogJ2F1dGgvbWlzc2luZy12ZXJpZmljYXRpb24tY29kZScsXG4gIE1JU1NJTkdfQ09OVElOVUVfVVJJOiAnYXV0aC9taXNzaW5nLWNvbnRpbnVlLXVyaScsXG4gIE1JU1NJTkdfSUZSQU1FX1NUQVJUOiAnYXV0aC9taXNzaW5nLWlmcmFtZS1zdGFydCcsXG4gIE1JU1NJTkdfSU9TX0JVTkRMRV9JRDogJ2F1dGgvbWlzc2luZy1pb3MtYnVuZGxlLWlkJyxcbiAgTUlTU0lOR19PUl9JTlZBTElEX05PTkNFOiAnYXV0aC9taXNzaW5nLW9yLWludmFsaWQtbm9uY2UnLFxuICBNSVNTSU5HX01GQV9JTkZPOiAnYXV0aC9taXNzaW5nLW11bHRpLWZhY3Rvci1pbmZvJyxcbiAgTUlTU0lOR19NRkFfU0VTU0lPTjogJ2F1dGgvbWlzc2luZy1tdWx0aS1mYWN0b3Itc2Vzc2lvbicsXG4gIE1JU1NJTkdfUEhPTkVfTlVNQkVSOiAnYXV0aC9taXNzaW5nLXBob25lLW51bWJlcicsXG4gIE1JU1NJTkdfUEFTU1dPUkQ6ICdhdXRoL21pc3NpbmctcGFzc3dvcmQnLFxuICBNSVNTSU5HX1NFU1NJT05fSU5GTzogJ2F1dGgvbWlzc2luZy12ZXJpZmljYXRpb24taWQnLFxuICBNT0RVTEVfREVTVFJPWUVEOiAnYXV0aC9hcHAtZGVsZXRlZCcsXG4gIE5FRURfQ09ORklSTUFUSU9OOiAnYXV0aC9hY2NvdW50LWV4aXN0cy13aXRoLWRpZmZlcmVudC1jcmVkZW50aWFsJyxcbiAgTkVUV09SS19SRVFVRVNUX0ZBSUxFRDogJ2F1dGgvbmV0d29yay1yZXF1ZXN0LWZhaWxlZCcsXG4gIE5VTExfVVNFUjogJ2F1dGgvbnVsbC11c2VyJyxcbiAgTk9fQVVUSF9FVkVOVDogJ2F1dGgvbm8tYXV0aC1ldmVudCcsXG4gIE5PX1NVQ0hfUFJPVklERVI6ICdhdXRoL25vLXN1Y2gtcHJvdmlkZXInLFxuICBPUEVSQVRJT05fTk9UX0FMTE9XRUQ6ICdhdXRoL29wZXJhdGlvbi1ub3QtYWxsb3dlZCcsXG4gIE9QRVJBVElPTl9OT1RfU1VQUE9SVEVEOiAnYXV0aC9vcGVyYXRpb24tbm90LXN1cHBvcnRlZC1pbi10aGlzLWVudmlyb25tZW50JyxcbiAgUE9QVVBfQkxPQ0tFRDogJ2F1dGgvcG9wdXAtYmxvY2tlZCcsXG4gIFBPUFVQX0NMT1NFRF9CWV9VU0VSOiAnYXV0aC9wb3B1cC1jbG9zZWQtYnktdXNlcicsXG4gIFBST1ZJREVSX0FMUkVBRFlfTElOS0VEOiAnYXV0aC9wcm92aWRlci1hbHJlYWR5LWxpbmtlZCcsXG4gIFFVT1RBX0VYQ0VFREVEOiAnYXV0aC9xdW90YS1leGNlZWRlZCcsXG4gIFJFRElSRUNUX0NBTkNFTExFRF9CWV9VU0VSOiAnYXV0aC9yZWRpcmVjdC1jYW5jZWxsZWQtYnktdXNlcicsXG4gIFJFRElSRUNUX09QRVJBVElPTl9QRU5ESU5HOiAnYXV0aC9yZWRpcmVjdC1vcGVyYXRpb24tcGVuZGluZycsXG4gIFJFSkVDVEVEX0NSRURFTlRJQUw6ICdhdXRoL3JlamVjdGVkLWNyZWRlbnRpYWwnLFxuICBTRUNPTkRfRkFDVE9SX0FMUkVBRFlfRU5ST0xMRUQ6ICdhdXRoL3NlY29uZC1mYWN0b3ItYWxyZWFkeS1pbi11c2UnLFxuICBTRUNPTkRfRkFDVE9SX0xJTUlUX0VYQ0VFREVEOiAnYXV0aC9tYXhpbXVtLXNlY29uZC1mYWN0b3ItY291bnQtZXhjZWVkZWQnLFxuICBURU5BTlRfSURfTUlTTUFUQ0g6ICdhdXRoL3RlbmFudC1pZC1taXNtYXRjaCcsXG4gIFRJTUVPVVQ6ICdhdXRoL3RpbWVvdXQnLFxuICBUT0tFTl9FWFBJUkVEOiAnYXV0aC91c2VyLXRva2VuLWV4cGlyZWQnLFxuICBUT09fTUFOWV9BVFRFTVBUU19UUllfTEFURVI6ICdhdXRoL3Rvby1tYW55LXJlcXVlc3RzJyxcbiAgVU5BVVRIT1JJWkVEX0RPTUFJTjogJ2F1dGgvdW5hdXRob3JpemVkLWNvbnRpbnVlLXVyaScsXG4gIFVOU1VQUE9SVEVEX0ZJUlNUX0ZBQ1RPUjogJ2F1dGgvdW5zdXBwb3J0ZWQtZmlyc3QtZmFjdG9yJyxcbiAgVU5TVVBQT1JURURfUEVSU0lTVEVOQ0U6ICdhdXRoL3Vuc3VwcG9ydGVkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBVTlNVUFBPUlRFRF9URU5BTlRfT1BFUkFUSU9OOiAnYXV0aC91bnN1cHBvcnRlZC10ZW5hbnQtb3BlcmF0aW9uJyxcbiAgVU5WRVJJRklFRF9FTUFJTDogJ2F1dGgvdW52ZXJpZmllZC1lbWFpbCcsXG4gIFVTRVJfQ0FOQ0VMTEVEOiAnYXV0aC91c2VyLWNhbmNlbGxlZCcsXG4gIFVTRVJfREVMRVRFRDogJ2F1dGgvdXNlci1ub3QtZm91bmQnLFxuICBVU0VSX0RJU0FCTEVEOiAnYXV0aC91c2VyLWRpc2FibGVkJyxcbiAgVVNFUl9NSVNNQVRDSDogJ2F1dGgvdXNlci1taXNtYXRjaCcsXG4gIFVTRVJfU0lHTkVEX09VVDogJ2F1dGgvdXNlci1zaWduZWQtb3V0JyxcbiAgV0VBS19QQVNTV09SRDogJ2F1dGgvd2Vhay1wYXNzd29yZCcsXG4gIFdFQl9TVE9SQUdFX1VOU1VQUE9SVEVEOiAnYXV0aC93ZWItc3RvcmFnZS11bnN1cHBvcnRlZCcsXG4gIEFMUkVBRFlfSU5JVElBTElaRUQ6ICdhdXRoL2FscmVhZHktaW5pdGlhbGl6ZWQnLFxuICBSRUNBUFRDSEFfTk9UX0VOQUJMRUQ6ICdhdXRoL3JlY2FwdGNoYS1ub3QtZW5hYmxlZCcsXG4gIE1JU1NJTkdfUkVDQVBUQ0hBX1RPS0VOOiAnYXV0aC9taXNzaW5nLXJlY2FwdGNoYS10b2tlbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX1RPS0VOOiAnYXV0aC9pbnZhbGlkLXJlY2FwdGNoYS10b2tlbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX0FDVElPTjogJ2F1dGgvaW52YWxpZC1yZWNhcHRjaGEtYWN0aW9uJyxcbiAgTUlTU0lOR19DTElFTlRfVFlQRTogJ2F1dGgvbWlzc2luZy1jbGllbnQtdHlwZScsXG4gIE1JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT046ICdhdXRoL21pc3NpbmctcmVjYXB0Y2hhLXZlcnNpb24nLFxuICBJTlZBTElEX1JFQ0FQVENIQV9WRVJTSU9OOiAnYXV0aC9pbnZhbGlkLXJlY2FwdGNoYS12ZXJzaW9uJyxcbiAgSU5WQUxJRF9SRVFfVFlQRTogJ2F1dGgvaW52YWxpZC1yZXEtdHlwZScsXG4gIElOVkFMSURfSE9TVElOR19MSU5LX0RPTUFJTjogJ2F1dGgvaW52YWxpZC1ob3N0aW5nLWxpbmstZG9tYWluJ1xufSBhcyBjb25zdDtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBMb2dnZXIsIExvZ0xldmVsIH0gZnJvbSAnQGZpcmViYXNlL2xvZ2dlcic7XG5pbXBvcnQgeyBTREtfVkVSU0lPTiB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuXG5leHBvcnQgeyBMb2dMZXZlbCB9O1xuXG5jb25zdCBsb2dDbGllbnQgPSBuZXcgTG9nZ2VyKCdAZmlyZWJhc2UvYXV0aCcpO1xuXG4vLyBIZWxwZXIgbWV0aG9kcyBhcmUgbmVlZGVkIGJlY2F1c2UgdmFyaWFibGVzIGNhbid0IGJlIGV4cG9ydGVkIGFzIHJlYWQvd3JpdGVcbmV4cG9ydCBmdW5jdGlvbiBfZ2V0TG9nTGV2ZWwoKTogTG9nTGV2ZWwge1xuICByZXR1cm4gbG9nQ2xpZW50LmxvZ0xldmVsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3NldExvZ0xldmVsKG5ld0xldmVsOiBMb2dMZXZlbCk6IHZvaWQge1xuICBsb2dDbGllbnQubG9nTGV2ZWwgPSBuZXdMZXZlbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9sb2dEZWJ1Zyhtc2c6IHN0cmluZywgLi4uYXJnczogc3RyaW5nW10pOiB2b2lkIHtcbiAgaWYgKGxvZ0NsaWVudC5sb2dMZXZlbCA8PSBMb2dMZXZlbC5ERUJVRykge1xuICAgIGxvZ0NsaWVudC5kZWJ1ZyhgQXV0aCAoJHtTREtfVkVSU0lPTn0pOiAke21zZ31gLCAuLi5hcmdzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gX2xvZ1dhcm4obXNnOiBzdHJpbmcsIC4uLmFyZ3M6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGlmIChsb2dDbGllbnQubG9nTGV2ZWwgPD0gTG9nTGV2ZWwuV0FSTikge1xuICAgIGxvZ0NsaWVudC53YXJuKGBBdXRoICgke1NES19WRVJTSU9OfSk6ICR7bXNnfWAsIC4uLmFyZ3MpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfbG9nRXJyb3IobXNnOiBzdHJpbmcsIC4uLmFyZ3M6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGlmIChsb2dDbGllbnQubG9nTGV2ZWwgPD0gTG9nTGV2ZWwuRVJST1IpIHtcbiAgICBsb2dDbGllbnQuZXJyb3IoYEF1dGggKCR7U0RLX1ZFUlNJT059KTogJHttc2d9YCwgLi4uYXJncyk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEVycm9yRmFjdG9yeSwgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHtcbiAgX0RFRkFVTFRfQVVUSF9FUlJPUl9GQUNUT1JZLFxuICBBdXRoRXJyb3JDb2RlLFxuICBBdXRoRXJyb3JQYXJhbXMsXG4gIHByb2RFcnJvck1hcCxcbiAgRXJyb3JNYXBSZXRyaWV2ZXJcbn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9sb2dFcnJvciB9IGZyb20gJy4vbG9nJztcblxudHlwZSBBdXRoRXJyb3JMaXN0UGFyYW1zPEs+ID0gSyBleHRlbmRzIGtleW9mIEF1dGhFcnJvclBhcmFtc1xuICA/IFtBdXRoRXJyb3JQYXJhbXNbS11dXG4gIDogW107XG50eXBlIExlc3NBcHBOYW1lPEsgZXh0ZW5kcyBBdXRoRXJyb3JDb2RlPiA9IE9taXQ8QXV0aEVycm9yUGFyYW1zW0tdLCAnYXBwTmFtZSc+O1xuXG4vKipcbiAqIFVuY29uZGl0aW9uYWxseSBmYWlscywgdGhyb3dpbmcgYSBkZXZlbG9wZXIgZmFjaW5nIElOVEVSTkFMX0VSUk9SXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGZhaWwoYXV0aCwgQXV0aEVycm9yQ29kZS5NRkFfUkVRVUlSRUQpOyAgLy8gRXJyb3I6IHRoZSBNRkFfUkVRVUlSRUQgZXJyb3IgbmVlZHMgbW9yZSBwYXJhbXMgdGhhbiBhcHBOYW1lXG4gKiBmYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVELCB7c2VydmVyUmVzcG9uc2V9KTsgIC8vIENvbXBpbGVzXG4gKiBmYWlsKEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpOyAgLy8gQ29tcGlsZXM7IGludGVybmFsIGVycm9yIGRvZXMgbm90IG5lZWQgYXBwTmFtZVxuICogZmFpbChBdXRoRXJyb3JDb2RlLlVTRVJfREVMRVRFRCk7ICAvLyBFcnJvcjogVVNFUl9ERUxFVEVEIHJlcXVpcmVzIGFwcCBuYW1lXG4gKiBmYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuVVNFUl9ERUxFVEVEKTsgIC8vIENvbXBpbGVzOyBVU0VSX0RFTEVURUQgX29ubHlfIG5lZWRzIGFwcCBuYW1lXG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gYXBwTmFtZSBBcHAgbmFtZSBmb3IgdGFnZ2luZyB0aGUgZXJyb3JcbiAqIEB0aHJvd3MgRmlyZWJhc2VFcnJvclxuICovXG5leHBvcnQgZnVuY3Rpb24gX2ZhaWw8SyBleHRlbmRzIEF1dGhFcnJvckNvZGU+KFxuICBjb2RlOiBLLFxuICAuLi5kYXRhOiB7fSBleHRlbmRzIEF1dGhFcnJvclBhcmFtc1tLXVxuICAgID8gW0F1dGhFcnJvclBhcmFtc1tLXT9dXG4gICAgOiBbQXV0aEVycm9yUGFyYW1zW0tdXVxuKTogbmV2ZXI7XG5leHBvcnQgZnVuY3Rpb24gX2ZhaWw8SyBleHRlbmRzIEF1dGhFcnJvckNvZGU+KFxuICBhdXRoOiBBdXRoLFxuICBjb2RlOiBLLFxuICAuLi5kYXRhOiB7fSBleHRlbmRzIExlc3NBcHBOYW1lPEs+ID8gW0xlc3NBcHBOYW1lPEs+P10gOiBbTGVzc0FwcE5hbWU8Sz5dXG4pOiBuZXZlcjtcbmV4cG9ydCBmdW5jdGlvbiBfZmFpbDxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGF1dGhPckNvZGU6IEF1dGggfCBLLFxuICAuLi5yZXN0OiB1bmtub3duW11cbik6IG5ldmVyIHtcbiAgdGhyb3cgY3JlYXRlRXJyb3JJbnRlcm5hbChhdXRoT3JDb2RlLCAuLi5yZXN0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9jcmVhdGVFcnJvcjxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGNvZGU6IEssXG4gIC4uLmRhdGE6IHt9IGV4dGVuZHMgQXV0aEVycm9yUGFyYW1zW0tdXG4gICAgPyBbQXV0aEVycm9yUGFyYW1zW0tdP11cbiAgICA6IFtBdXRoRXJyb3JQYXJhbXNbS11dXG4pOiBGaXJlYmFzZUVycm9yO1xuZXhwb3J0IGZ1bmN0aW9uIF9jcmVhdGVFcnJvcjxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGF1dGg6IEF1dGgsXG4gIGNvZGU6IEssXG4gIC4uLmRhdGE6IHt9IGV4dGVuZHMgTGVzc0FwcE5hbWU8Sz4gPyBbTGVzc0FwcE5hbWU8Sz4/XSA6IFtMZXNzQXBwTmFtZTxLPl1cbik6IEZpcmViYXNlRXJyb3I7XG5leHBvcnQgZnVuY3Rpb24gX2NyZWF0ZUVycm9yPEsgZXh0ZW5kcyBBdXRoRXJyb3JDb2RlPihcbiAgYXV0aE9yQ29kZTogQXV0aCB8IEssXG4gIC4uLnJlc3Q6IHVua25vd25bXVxuKTogRmlyZWJhc2VFcnJvciB7XG4gIHJldHVybiBjcmVhdGVFcnJvckludGVybmFsKGF1dGhPckNvZGUsIC4uLnJlc3QpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2Vycm9yV2l0aEN1c3RvbU1lc3NhZ2UoXG4gIGF1dGg6IEF1dGgsXG4gIGNvZGU6IEF1dGhFcnJvckNvZGUsXG4gIG1lc3NhZ2U6IHN0cmluZ1xuKTogRmlyZWJhc2VFcnJvciB7XG4gIGNvbnN0IGVycm9yTWFwID0ge1xuICAgIC4uLihwcm9kRXJyb3JNYXAgYXMgRXJyb3JNYXBSZXRyaWV2ZXIpKCksXG4gICAgW2NvZGVdOiBtZXNzYWdlXG4gIH07XG4gIGNvbnN0IGZhY3RvcnkgPSBuZXcgRXJyb3JGYWN0b3J5PEF1dGhFcnJvckNvZGUsIEF1dGhFcnJvclBhcmFtcz4oXG4gICAgJ2F1dGgnLFxuICAgICdGaXJlYmFzZScsXG4gICAgZXJyb3JNYXBcbiAgKTtcbiAgcmV0dXJuIGZhY3RvcnkuY3JlYXRlKGNvZGUsIHtcbiAgICBhcHBOYW1lOiBhdXRoLm5hbWVcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcihcbiAgYXV0aDogQXV0aFxuKTogRmlyZWJhc2VFcnJvciB7XG4gIHJldHVybiBfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZShcbiAgICBhdXRoLFxuICAgIEF1dGhFcnJvckNvZGUuT1BFUkFUSU9OX05PVF9TVVBQT1JURUQsXG4gICAgJ09wZXJhdGlvbnMgdGhhdCBhbHRlciB0aGUgY3VycmVudCB1c2VyIGFyZSBub3Qgc3VwcG9ydGVkIGluIGNvbmp1bmN0aW9uIHdpdGggRmlyZWJhc2VTZXJ2ZXJBcHAnXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfYXNzZXJ0SW5zdGFuY2VPZihcbiAgYXV0aDogQXV0aCxcbiAgb2JqZWN0OiBvYmplY3QsXG4gIGluc3RhbmNlOiB1bmtub3duXG4pOiB2b2lkIHtcbiAgY29uc3QgY29uc3RydWN0b3JJbnN0YW5jZSA9IGluc3RhbmNlIGFzIHsgbmV3ICguLi5hcmdzOiB1bmtub3duW10pOiB1bmtub3duIH07XG4gIGlmICghKG9iamVjdCBpbnN0YW5jZW9mIGNvbnN0cnVjdG9ySW5zdGFuY2UpKSB7XG4gICAgaWYgKGNvbnN0cnVjdG9ySW5zdGFuY2UubmFtZSAhPT0gb2JqZWN0LmNvbnN0cnVjdG9yLm5hbWUpIHtcbiAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IpO1xuICAgIH1cblxuICAgIHRocm93IF9lcnJvcldpdGhDdXN0b21NZXNzYWdlKFxuICAgICAgYXV0aCxcbiAgICAgIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IsXG4gICAgICBgVHlwZSBvZiAke29iamVjdC5jb25zdHJ1Y3Rvci5uYW1lfSBkb2VzIG5vdCBtYXRjaCBleHBlY3RlZCBpbnN0YW5jZS5gICtcbiAgICAgICAgYERpZCB5b3UgcGFzcyBhIHJlZmVyZW5jZSBmcm9tIGEgZGlmZmVyZW50IEF1dGggU0RLP2BcbiAgICApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUVycm9ySW50ZXJuYWw8SyBleHRlbmRzIEF1dGhFcnJvckNvZGU+KFxuICBhdXRoT3JDb2RlOiBBdXRoIHwgSyxcbiAgLi4ucmVzdDogdW5rbm93bltdXG4pOiBGaXJlYmFzZUVycm9yIHtcbiAgaWYgKHR5cGVvZiBhdXRoT3JDb2RlICE9PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGNvZGUgPSByZXN0WzBdIGFzIEs7XG4gICAgY29uc3QgZnVsbFBhcmFtcyA9IFsuLi5yZXN0LnNsaWNlKDEpXSBhcyBBdXRoRXJyb3JMaXN0UGFyYW1zPEs+O1xuICAgIGlmIChmdWxsUGFyYW1zWzBdKSB7XG4gICAgICBmdWxsUGFyYW1zWzBdLmFwcE5hbWUgPSBhdXRoT3JDb2RlLm5hbWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIChhdXRoT3JDb2RlIGFzIEF1dGhJbnRlcm5hbCkuX2Vycm9yRmFjdG9yeS5jcmVhdGUoXG4gICAgICBjb2RlLFxuICAgICAgLi4uZnVsbFBhcmFtc1xuICAgICk7XG4gIH1cblxuICByZXR1cm4gX0RFRkFVTFRfQVVUSF9FUlJPUl9GQUNUT1JZLmNyZWF0ZShcbiAgICBhdXRoT3JDb2RlLFxuICAgIC4uLihyZXN0IGFzIEF1dGhFcnJvckxpc3RQYXJhbXM8Sz4pXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfYXNzZXJ0PEsgZXh0ZW5kcyBBdXRoRXJyb3JDb2RlPihcbiAgYXNzZXJ0aW9uOiB1bmtub3duLFxuICBjb2RlOiBLLFxuICAuLi5kYXRhOiB7fSBleHRlbmRzIEF1dGhFcnJvclBhcmFtc1tLXVxuICAgID8gW0F1dGhFcnJvclBhcmFtc1tLXT9dXG4gICAgOiBbQXV0aEVycm9yUGFyYW1zW0tdXVxuKTogYXNzZXJ0cyBhc3NlcnRpb247XG5leHBvcnQgZnVuY3Rpb24gX2Fzc2VydDxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGFzc2VydGlvbjogdW5rbm93bixcbiAgYXV0aDogQXV0aCxcbiAgY29kZTogSyxcbiAgLi4uZGF0YToge30gZXh0ZW5kcyBMZXNzQXBwTmFtZTxLPiA/IFtMZXNzQXBwTmFtZTxLPj9dIDogW0xlc3NBcHBOYW1lPEs+XVxuKTogYXNzZXJ0cyBhc3NlcnRpb247XG5leHBvcnQgZnVuY3Rpb24gX2Fzc2VydDxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGFzc2VydGlvbjogdW5rbm93bixcbiAgYXV0aE9yQ29kZTogQXV0aCB8IEssXG4gIC4uLnJlc3Q6IHVua25vd25bXVxuKTogYXNzZXJ0cyBhc3NlcnRpb24ge1xuICBpZiAoIWFzc2VydGlvbikge1xuICAgIHRocm93IGNyZWF0ZUVycm9ySW50ZXJuYWwoYXV0aE9yQ29kZSwgLi4ucmVzdCk7XG4gIH1cbn1cblxuLy8gV2UgcmVhbGx5IGRvIHdhbnQgdG8gYWNjZXB0IGxpdGVyYWxseSBhbnkgZnVuY3Rpb24gdHlwZSBoZXJlXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xudHlwZSBUeXBlRXhwZWN0YXRpb24gPSBGdW5jdGlvbiB8IHN0cmluZyB8IE1hcFR5cGU7XG5cbmludGVyZmFjZSBNYXBUeXBlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgVHlwZUV4cGVjdGF0aW9uIHwgT3B0aW9uYWw+IHt9XG5cbmNsYXNzIE9wdGlvbmFsIHtcbiAgY29uc3RydWN0b3IocmVhZG9ubHkgdHlwZTogVHlwZUV4cGVjdGF0aW9uKSB7fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb3B0KHR5cGU6IFR5cGVFeHBlY3RhdGlvbik6IE9wdGlvbmFsIHtcbiAgcmV0dXJuIG5ldyBPcHRpb25hbCh0eXBlKTtcbn1cblxuLyoqXG4gKiBBc3NlcnRzIHRoZSBydW50aW1lIHR5cGVzIG9mIGFyZ3VtZW50cy4gVGhlICdleHBlY3RlZCcgZmllbGQgY2FuIGJlIG9uZSBvZlxuICogYSBjbGFzcywgYSBzdHJpbmcgKHJlcHJlc2VudGluZyBhIFwidHlwZW9mXCIgY2FsbCksIG9yIGEgcmVjb3JkIG1hcCBvZiBuYW1lXG4gKiB0byB0eXBlLiBGdXJ0aGVybW9yZSwgdGhlIG9wdCgpIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIG1hcmsgYSBmaWVsZCBhc1xuICogb3B0aW9uYWwuIEZvciBleGFtcGxlOlxuICpcbiAqIGZ1bmN0aW9uIGZvbyhhdXRoOiBBdXRoLCBwcm9maWxlOiB7ZGlzcGxheU5hbWU/OiBzdHJpbmd9LCB1cGRhdGUgPSBmYWxzZSkge1xuICogICBhc3NlcnRUeXBlcyhhcmd1bWVudHMsIFtBdXRoSW1wbCwge2Rpc3BsYXlOYW1lOiBvcHQoJ3N0cmluZycpfSwgb3B0KCdib29sZWFuJyldKTtcbiAqIH1cbiAqXG4gKiBvcHQoKSBjYW4gYmUgdXNlZCBmb3IgYW55IHR5cGU6XG4gKiBmdW5jdGlvbiBmb28oYXV0aD86IEF1dGgpIHtcbiAqICAgYXNzZXJ0VHlwZXMoYXJndW1lbnRzLCBbb3B0KEF1dGhJbXBsKV0pO1xuICogfVxuICpcbiAqIFRoZSBzdHJpbmcgdHlwZXMgY2FuIGJlIG9yJ2QgdG9nZXRoZXIsIGFuZCB5b3UgY2FuIHVzZSBcIm51bGxcIiBhcyB3ZWxsIChub3RlXG4gKiB0aGF0IHR5cGVvZiBudWxsID09PSAnb2JqZWN0JzsgdGhpcyBpcyBhbiBlZGdlIGNhc2UpLiBGb3IgZXhhbXBsZTpcbiAqXG4gKiBmdW5jdGlvbiBmb28ocHJvZmlsZToge2Rpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbH0pIHtcbiAqICAgYXNzZXJ0VHlwZXMoYXJndW1lbnRzLCBbe2Rpc3BsYXlOYW1lOiBvcHQoJ3N0cmluZ3xudWxsJyl9XSk7XG4gKiB9XG4gKlxuICogQHBhcmFtIGFyZ3NcbiAqIEBwYXJhbSBleHBlY3RlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0VHlwZXMoXG4gIGFyZ3M6IE9taXQ8SUFyZ3VtZW50cywgJ2NhbGxlZSc+LFxuICAuLi5leHBlY3RlZDogQXJyYXk8VHlwZUV4cGVjdGF0aW9uIHwgT3B0aW9uYWw+XG4pOiB2b2lkIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID4gZXhwZWN0ZWQubGVuZ3RoKSB7XG4gICAgX2ZhaWwoQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUiwge30pO1xuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBleHBlY3RlZC5sZW5ndGg7IGkrKykge1xuICAgIGxldCBleHBlY3QgPSBleHBlY3RlZFtpXTtcbiAgICBjb25zdCBhcmcgPSBhcmdzW2ldO1xuXG4gICAgaWYgKGV4cGVjdCBpbnN0YW5jZW9mIE9wdGlvbmFsKSB7XG4gICAgICAvLyBJZiB0aGUgYXJnIGlzIHVuZGVmaW5lZCwgdGhlbiBpdCBtYXRjaGVzIFwib3B0aW9uYWxcIiBhbmQgd2UgY2FuIG1vdmUgdG9cbiAgICAgIC8vIHRoZSBuZXh0IGFyZ1xuICAgICAgaWYgKHR5cGVvZiBhcmcgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgZXhwZWN0ID0gZXhwZWN0LnR5cGU7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBleHBlY3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBIYW5kbGUgdGhlIGVkZ2UgY2FzZSBmb3IgbnVsbCBiZWNhdXNlIHR5cGVvZiBudWxsID09PSAnb2JqZWN0J1xuICAgICAgaWYgKGV4cGVjdC5pbmNsdWRlcygnbnVsbCcpICYmIGFyZyA9PT0gbnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVxdWlyZWQgPSBleHBlY3Quc3BsaXQoJ3wnKTtcbiAgICAgIF9hc3NlcnQocmVxdWlyZWQuaW5jbHVkZXModHlwZW9mIGFyZyksIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IsIHt9KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBlY3QgPT09ICdvYmplY3QnKSB7XG4gICAgICAvLyBSZWN1cnNpdmVseSBjaGVjayByZWNvcmQgYXJndW1lbnRzXG4gICAgICBjb25zdCByZWNvcmQgPSBhcmcgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICBjb25zdCBtYXAgPSBleHBlY3QgYXMgTWFwVHlwZTtcbiAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhleHBlY3QpO1xuXG4gICAgICBhc3NlcnRUeXBlcyhcbiAgICAgICAga2V5cy5tYXAoayA9PiByZWNvcmRba10pLFxuICAgICAgICAuLi5rZXlzLm1hcChrID0+IG1hcFtrXSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIF9hc3NlcnQoYXJnIGluc3RhbmNlb2YgZXhwZWN0LCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SLCB7fSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVW5jb25kaXRpb25hbGx5IGZhaWxzLCB0aHJvd2luZyBhbiBpbnRlcm5hbCBlcnJvciB3aXRoIHRoZSBnaXZlbiBtZXNzYWdlLlxuICpcbiAqIEBwYXJhbSBmYWlsdXJlIHR5cGUgb2YgZmFpbHVyZSBlbmNvdW50ZXJlZFxuICogQHRocm93cyBFcnJvclxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdGYWlsKGZhaWx1cmU6IHN0cmluZyk6IG5ldmVyIHtcbiAgLy8gTG9nIHRoZSBmYWlsdXJlIGluIGFkZGl0aW9uIHRvIHRocm93IGFuIGV4Y2VwdGlvbiwganVzdCBpbiBjYXNlIHRoZVxuICAvLyBleGNlcHRpb24gaXMgc3dhbGxvd2VkLlxuICBjb25zdCBtZXNzYWdlID0gYElOVEVSTkFMIEFTU0VSVElPTiBGQUlMRUQ6IGAgKyBmYWlsdXJlO1xuICBfbG9nRXJyb3IobWVzc2FnZSk7XG5cbiAgLy8gTk9URTogV2UgZG9uJ3QgdXNlIEZpcmViYXNlRXJyb3IgaGVyZSBiZWNhdXNlIHRoZXNlIGFyZSBpbnRlcm5hbCBmYWlsdXJlc1xuICAvLyB0aGF0IGNhbm5vdCBiZSBoYW5kbGVkIGJ5IHRoZSB1c2VyLiAoQWxzbyBpdCB3b3VsZCBjcmVhdGUgYSBjaXJjdWxhclxuICAvLyBkZXBlbmRlbmN5IGJldHdlZW4gdGhlIGVycm9yIGFuZCBhc3NlcnQgbW9kdWxlcyB3aGljaCBkb2Vzbid0IHdvcmsuKVxuICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRmFpbHMgaWYgdGhlIGdpdmVuIGFzc2VydGlvbiBjb25kaXRpb24gaXMgZmFsc2UsIHRocm93aW5nIGFuIEVycm9yIHdpdGggdGhlXG4gKiBnaXZlbiBtZXNzYWdlIGlmIGl0IGRpZC5cbiAqXG4gKiBAcGFyYW0gYXNzZXJ0aW9uXG4gKiBAcGFyYW0gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdBc3NlcnQoXG4gIGFzc2VydGlvbjogdW5rbm93bixcbiAgbWVzc2FnZTogc3RyaW5nXG4pOiBhc3NlcnRzIGFzc2VydGlvbiB7XG4gIGlmICghYXNzZXJ0aW9uKSB7XG4gICAgZGVidWdGYWlsKG1lc3NhZ2UpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIF9nZXRDdXJyZW50VXJsKCk6IHN0cmluZyB7XG4gIHJldHVybiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHNlbGYubG9jYXRpb24/LmhyZWYpIHx8ICcnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSHR0cE9ySHR0cHMoKTogYm9vbGVhbiB7XG4gIHJldHVybiBfZ2V0Q3VycmVudFNjaGVtZSgpID09PSAnaHR0cDonIHx8IF9nZXRDdXJyZW50U2NoZW1lKCkgPT09ICdodHRwczonO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2dldEN1cnJlbnRTY2hlbWUoKTogc3RyaW5nIHwgbnVsbCB7XG4gIHJldHVybiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHNlbGYubG9jYXRpb24/LnByb3RvY29sKSB8fCBudWxsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGlzQnJvd3NlckV4dGVuc2lvbiB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IF9pc0h0dHBPckh0dHBzIH0gZnJvbSAnLi9sb2NhdGlvbic7XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGJyb3dzZXIgaXMgd29ya2luZyBvbmxpbmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9pc09ubGluZSgpOiBib29sZWFuIHtcbiAgaWYgKFxuICAgIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmXG4gICAgbmF2aWdhdG9yICYmXG4gICAgJ29uTGluZScgaW4gbmF2aWdhdG9yICYmXG4gICAgdHlwZW9mIG5hdmlnYXRvci5vbkxpbmUgPT09ICdib29sZWFuJyAmJlxuICAgIC8vIEFwcGx5IG9ubHkgZm9yIHRyYWRpdGlvbmFsIHdlYiBhcHBzIGFuZCBDaHJvbWUgZXh0ZW5zaW9ucy5cbiAgICAvLyBUaGlzIGlzIGVzcGVjaWFsbHkgdHJ1ZSBmb3IgQ29yZG92YSBhcHBzIHdoaWNoIGhhdmUgdW5yZWxpYWJsZVxuICAgIC8vIG5hdmlnYXRvci5vbkxpbmUgYmVoYXZpb3IgdW5sZXNzIGNvcmRvdmEtcGx1Z2luLW5ldHdvcmstaW5mb3JtYXRpb24gaXNcbiAgICAvLyBpbnN0YWxsZWQgd2hpY2ggb3ZlcndyaXRlcyB0aGUgbmF0aXZlIG5hdmlnYXRvci5vbkxpbmUgdmFsdWUgYW5kXG4gICAgLy8gZGVmaW5lcyBuYXZpZ2F0b3IuY29ubmVjdGlvbi5cbiAgICAoX2lzSHR0cE9ySHR0cHMoKSB8fCBpc0Jyb3dzZXJFeHRlbnNpb24oKSB8fCAnY29ubmVjdGlvbicgaW4gbmF2aWdhdG9yKVxuICApIHtcbiAgICByZXR1cm4gbmF2aWdhdG9yLm9uTGluZTtcbiAgfVxuICAvLyBJZiB3ZSBjYW4ndCBkZXRlcm1pbmUgdGhlIHN0YXRlLCBhc3N1bWUgaXQgaXMgb25saW5lLlxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9nZXRVc2VyTGFuZ3VhZ2UoKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IG5hdmlnYXRvckxhbmd1YWdlOiBOYXZpZ2F0b3JMYW5ndWFnZSA9IG5hdmlnYXRvcjtcbiAgcmV0dXJuIChcbiAgICAvLyBNb3N0IHJlbGlhYmxlLCBidXQgb25seSBzdXBwb3J0ZWQgaW4gQ2hyb21lL0ZpcmVmb3guXG4gICAgKG5hdmlnYXRvckxhbmd1YWdlLmxhbmd1YWdlcyAmJiBuYXZpZ2F0b3JMYW5ndWFnZS5sYW5ndWFnZXNbMF0pIHx8XG4gICAgLy8gU3VwcG9ydGVkIGluIG1vc3QgYnJvd3NlcnMsIGJ1dCByZXR1cm5zIHRoZSBsYW5ndWFnZSBvZiB0aGUgYnJvd3NlclxuICAgIC8vIFVJLCBub3QgdGhlIGxhbmd1YWdlIHNldCBpbiBicm93c2VyIHNldHRpbmdzLlxuICAgIG5hdmlnYXRvckxhbmd1YWdlLmxhbmd1YWdlIHx8XG4gICAgLy8gQ291bGRuJ3QgZGV0ZXJtaW5lIGxhbmd1YWdlLlxuICAgIG51bGxcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBpc01vYmlsZUNvcmRvdmEsIGlzUmVhY3ROYXRpdmUgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBfaXNPbmxpbmUgfSBmcm9tICcuL25hdmlnYXRvcic7XG5pbXBvcnQgeyBkZWJ1Z0Fzc2VydCB9IGZyb20gJy4vYXNzZXJ0JztcblxuZXhwb3J0IGNvbnN0IGVudW0gRGVsYXlNaW4ge1xuICBPRkZMSU5FID0gNTAwMFxufVxuXG4vKipcbiAqIEEgc3RydWN0dXJlIHRvIGhlbHAgcGljayBiZXR3ZWVuIGEgcmFuZ2Ugb2YgbG9uZyBhbmQgc2hvcnQgZGVsYXkgZHVyYXRpb25zXG4gKiBkZXBlbmRpbmcgb24gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIEluIGdlbmVyYWwsIHRoZSBsb25nIGRlbGF5IGlzIHVzZWQgZm9yXG4gKiBtb2JpbGUgZW52aXJvbm1lbnRzIHdoZXJlYXMgc2hvcnQgZGVsYXlzIGFyZSB1c2VkIGZvciBkZXNrdG9wIGVudmlyb25tZW50cy5cbiAqL1xuZXhwb3J0IGNsYXNzIERlbGF5IHtcbiAgLy8gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBvZmZsaW5lIGRlbGF5IHRpbWVvdXQgaW4gbXMuXG5cbiAgcHJpdmF0ZSByZWFkb25seSBpc01vYmlsZTogYm9vbGVhbjtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzaG9ydERlbGF5OiBudW1iZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBsb25nRGVsYXk6IG51bWJlclxuICApIHtcbiAgICAvLyBJbnRlcm5hbCBlcnJvciB3aGVuIGltcHJvcGVybHkgaW5pdGlhbGl6ZWQuXG4gICAgZGVidWdBc3NlcnQoXG4gICAgICBsb25nRGVsYXkgPiBzaG9ydERlbGF5LFxuICAgICAgJ1Nob3J0IGRlbGF5IHNob3VsZCBiZSBsZXNzIHRoYW4gbG9uZyBkZWxheSEnXG4gICAgKTtcbiAgICB0aGlzLmlzTW9iaWxlID0gaXNNb2JpbGVDb3Jkb3ZhKCkgfHwgaXNSZWFjdE5hdGl2ZSgpO1xuICB9XG5cbiAgZ2V0KCk6IG51bWJlciB7XG4gICAgaWYgKCFfaXNPbmxpbmUoKSkge1xuICAgICAgLy8gUGljayB0aGUgc2hvcnRlciB0aW1lb3V0LlxuICAgICAgcmV0dXJuIE1hdGgubWluKERlbGF5TWluLk9GRkxJTkUsIHRoaXMuc2hvcnREZWxheSk7XG4gICAgfVxuICAgIC8vIElmIHJ1bm5pbmcgaW4gYSBtb2JpbGUgZW52aXJvbm1lbnQsIHJldHVybiB0aGUgbG9uZyBkZWxheSwgb3RoZXJ3aXNlXG4gICAgLy8gcmV0dXJuIHRoZSBzaG9ydCBkZWxheS5cbiAgICAvLyBUaGlzIGNvdWxkIGJlIGltcHJvdmVkIGluIHRoZSBmdXR1cmUgdG8gZHluYW1pY2FsbHkgY2hhbmdlIGJhc2VkIG9uIG90aGVyXG4gICAgLy8gdmFyaWFibGVzIGluc3RlYWQgb2YganVzdCByZWFkaW5nIHRoZSBjdXJyZW50IGVudmlyb25tZW50LlxuICAgIHJldHVybiB0aGlzLmlzTW9iaWxlID8gdGhpcy5sb25nRGVsYXkgOiB0aGlzLnNob3J0RGVsYXk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgZGVidWdBc3NlcnQgfSBmcm9tICcuL2Fzc2VydCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBfZW11bGF0b3JVcmwoY29uZmlnOiBDb25maWdJbnRlcm5hbCwgcGF0aD86IHN0cmluZyk6IHN0cmluZyB7XG4gIGRlYnVnQXNzZXJ0KGNvbmZpZy5lbXVsYXRvciwgJ0VtdWxhdG9yIHNob3VsZCBhbHdheXMgYmUgc2V0IGhlcmUnKTtcbiAgY29uc3QgeyB1cmwgfSA9IGNvbmZpZy5lbXVsYXRvcjtcblxuICBpZiAoIXBhdGgpIHtcbiAgICByZXR1cm4gdXJsO1xuICB9XG5cbiAgcmV0dXJuIGAke3VybH0ke3BhdGguc3RhcnRzV2l0aCgnLycpID8gcGF0aC5zbGljZSgxKSA6IHBhdGh9YDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBkZWJ1Z0ZhaWwgfSBmcm9tICcuL2Fzc2VydCc7XG5cbmV4cG9ydCBjbGFzcyBGZXRjaFByb3ZpZGVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgZmV0Y2hJbXBsOiB0eXBlb2YgZmV0Y2ggfCBudWxsO1xuICBwcml2YXRlIHN0YXRpYyBoZWFkZXJzSW1wbDogdHlwZW9mIEhlYWRlcnMgfCBudWxsO1xuICBwcml2YXRlIHN0YXRpYyByZXNwb25zZUltcGw6IHR5cGVvZiBSZXNwb25zZSB8IG51bGw7XG5cbiAgc3RhdGljIGluaXRpYWxpemUoXG4gICAgZmV0Y2hJbXBsOiB0eXBlb2YgZmV0Y2gsXG4gICAgaGVhZGVyc0ltcGw/OiB0eXBlb2YgSGVhZGVycyxcbiAgICByZXNwb25zZUltcGw/OiB0eXBlb2YgUmVzcG9uc2VcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5mZXRjaEltcGwgPSBmZXRjaEltcGw7XG4gICAgaWYgKGhlYWRlcnNJbXBsKSB7XG4gICAgICB0aGlzLmhlYWRlcnNJbXBsID0gaGVhZGVyc0ltcGw7XG4gICAgfVxuICAgIGlmIChyZXNwb25zZUltcGwpIHtcbiAgICAgIHRoaXMucmVzcG9uc2VJbXBsID0gcmVzcG9uc2VJbXBsO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBmZXRjaCgpOiB0eXBlb2YgZmV0Y2gge1xuICAgIGlmICh0aGlzLmZldGNoSW1wbCkge1xuICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hJbXBsO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmICdmZXRjaCcgaW4gc2VsZikge1xuICAgICAgcmV0dXJuIHNlbGYuZmV0Y2g7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgJiYgZ2xvYmFsVGhpcy5mZXRjaCkge1xuICAgICAgcmV0dXJuIGdsb2JhbFRoaXMuZmV0Y2g7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZmV0Y2ggIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZmV0Y2g7XG4gICAgfVxuICAgIGRlYnVnRmFpbChcbiAgICAgICdDb3VsZCBub3QgZmluZCBmZXRjaCBpbXBsZW1lbnRhdGlvbiwgbWFrZSBzdXJlIHlvdSBjYWxsIEZldGNoUHJvdmlkZXIuaW5pdGlhbGl6ZSgpIHdpdGggYW4gYXBwcm9wcmlhdGUgcG9seWZpbGwnXG4gICAgKTtcbiAgfVxuXG4gIHN0YXRpYyBoZWFkZXJzKCk6IHR5cGVvZiBIZWFkZXJzIHtcbiAgICBpZiAodGhpcy5oZWFkZXJzSW1wbCkge1xuICAgICAgcmV0dXJuIHRoaXMuaGVhZGVyc0ltcGw7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgJiYgJ0hlYWRlcnMnIGluIHNlbGYpIHtcbiAgICAgIHJldHVybiBzZWxmLkhlYWRlcnM7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgJiYgZ2xvYmFsVGhpcy5IZWFkZXJzKSB7XG4gICAgICByZXR1cm4gZ2xvYmFsVGhpcy5IZWFkZXJzO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIEhlYWRlcnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gSGVhZGVycztcbiAgICB9XG4gICAgZGVidWdGYWlsKFxuICAgICAgJ0NvdWxkIG5vdCBmaW5kIEhlYWRlcnMgaW1wbGVtZW50YXRpb24sIG1ha2Ugc3VyZSB5b3UgY2FsbCBGZXRjaFByb3ZpZGVyLmluaXRpYWxpemUoKSB3aXRoIGFuIGFwcHJvcHJpYXRlIHBvbHlmaWxsJ1xuICAgICk7XG4gIH1cblxuICBzdGF0aWMgcmVzcG9uc2UoKTogdHlwZW9mIFJlc3BvbnNlIHtcbiAgICBpZiAodGhpcy5yZXNwb25zZUltcGwpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlc3BvbnNlSW1wbDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiAnUmVzcG9uc2UnIGluIHNlbGYpIHtcbiAgICAgIHJldHVybiBzZWxmLlJlc3BvbnNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbFRoaXMuUmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiBnbG9iYWxUaGlzLlJlc3BvbnNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIFJlc3BvbnNlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIFJlc3BvbnNlO1xuICAgIH1cbiAgICBkZWJ1Z0ZhaWwoXG4gICAgICAnQ291bGQgbm90IGZpbmQgUmVzcG9uc2UgaW1wbGVtZW50YXRpb24sIG1ha2Ugc3VyZSB5b3UgY2FsbCBGZXRjaFByb3ZpZGVyLmluaXRpYWxpemUoKSB3aXRoIGFuIGFwcHJvcHJpYXRlIHBvbHlmaWxsJ1xuICAgICk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuXG4vKipcbiAqIEVycm9ycyB0aGF0IGNhbiBiZSByZXR1cm5lZCBieSB0aGUgYmFja2VuZFxuICovXG5leHBvcnQgY29uc3QgZW51bSBTZXJ2ZXJFcnJvciB7XG4gIEFETUlOX09OTFlfT1BFUkFUSU9OID0gJ0FETUlOX09OTFlfT1BFUkFUSU9OJyxcbiAgQkxPQ0tJTkdfRlVOQ1RJT05fRVJST1JfUkVTUE9OU0UgPSAnQkxPQ0tJTkdfRlVOQ1RJT05fRVJST1JfUkVTUE9OU0UnLFxuICBDQVBUQ0hBX0NIRUNLX0ZBSUxFRCA9ICdDQVBUQ0hBX0NIRUNLX0ZBSUxFRCcsXG4gIENPUlNfVU5TVVBQT1JURUQgPSAnQ09SU19VTlNVUFBPUlRFRCcsXG4gIENSRURFTlRJQUxfTUlTTUFUQ0ggPSAnQ1JFREVOVElBTF9NSVNNQVRDSCcsXG4gIENSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTiA9ICdDUkVERU5USUFMX1RPT19PTERfTE9HSU5fQUdBSU4nLFxuICBEWU5BTUlDX0xJTktfTk9UX0FDVElWQVRFRCA9ICdEWU5BTUlDX0xJTktfTk9UX0FDVElWQVRFRCcsXG4gIEVNQUlMX0NIQU5HRV9ORUVEU19WRVJJRklDQVRJT04gPSAnRU1BSUxfQ0hBTkdFX05FRURTX1ZFUklGSUNBVElPTicsXG4gIEVNQUlMX0VYSVNUUyA9ICdFTUFJTF9FWElTVFMnLFxuICBFTUFJTF9OT1RfRk9VTkQgPSAnRU1BSUxfTk9UX0ZPVU5EJyxcbiAgRVhQSVJFRF9PT0JfQ09ERSA9ICdFWFBJUkVEX09PQl9DT0RFJyxcbiAgRkVERVJBVEVEX1VTRVJfSURfQUxSRUFEWV9MSU5LRUQgPSAnRkVERVJBVEVEX1VTRVJfSURfQUxSRUFEWV9MSU5LRUQnLFxuICBJTlZBTElEX0FQUF9DUkVERU5USUFMID0gJ0lOVkFMSURfQVBQX0NSRURFTlRJQUwnLFxuICBJTlZBTElEX0FQUF9JRCA9ICdJTlZBTElEX0FQUF9JRCcsXG4gIElOVkFMSURfQ0VSVF9IQVNIID0gJ0lOVkFMSURfQ0VSVF9IQVNIJyxcbiAgSU5WQUxJRF9DT0RFID0gJ0lOVkFMSURfQ09ERScsXG4gIElOVkFMSURfQ09OVElOVUVfVVJJID0gJ0lOVkFMSURfQ09OVElOVUVfVVJJJyxcbiAgSU5WQUxJRF9DVVNUT01fVE9LRU4gPSAnSU5WQUxJRF9DVVNUT01fVE9LRU4nLFxuICBJTlZBTElEX0RZTkFNSUNfTElOS19ET01BSU4gPSAnSU5WQUxJRF9EWU5BTUlDX0xJTktfRE9NQUlOJyxcbiAgSU5WQUxJRF9FTUFJTCA9ICdJTlZBTElEX0VNQUlMJyxcbiAgSU5WQUxJRF9JRF9UT0tFTiA9ICdJTlZBTElEX0lEX1RPS0VOJyxcbiAgSU5WQUxJRF9JRFBfUkVTUE9OU0UgPSAnSU5WQUxJRF9JRFBfUkVTUE9OU0UnLFxuICBJTlZBTElEX0lERU5USUZJRVIgPSAnSU5WQUxJRF9JREVOVElGSUVSJyxcbiAgSU5WQUxJRF9MT0dJTl9DUkVERU5USUFMUyA9ICdJTlZBTElEX0xPR0lOX0NSRURFTlRJQUxTJyxcbiAgSU5WQUxJRF9NRVNTQUdFX1BBWUxPQUQgPSAnSU5WQUxJRF9NRVNTQUdFX1BBWUxPQUQnLFxuICBJTlZBTElEX01GQV9QRU5ESU5HX0NSRURFTlRJQUwgPSAnSU5WQUxJRF9NRkFfUEVORElOR19DUkVERU5USUFMJyxcbiAgSU5WQUxJRF9PQVVUSF9DTElFTlRfSUQgPSAnSU5WQUxJRF9PQVVUSF9DTElFTlRfSUQnLFxuICBJTlZBTElEX09PQl9DT0RFID0gJ0lOVkFMSURfT09CX0NPREUnLFxuICBJTlZBTElEX1BBU1NXT1JEID0gJ0lOVkFMSURfUEFTU1dPUkQnLFxuICBJTlZBTElEX1BFTkRJTkdfVE9LRU4gPSAnSU5WQUxJRF9QRU5ESU5HX1RPS0VOJyxcbiAgSU5WQUxJRF9QSE9ORV9OVU1CRVIgPSAnSU5WQUxJRF9QSE9ORV9OVU1CRVInLFxuICBJTlZBTElEX1BST1ZJREVSX0lEID0gJ0lOVkFMSURfUFJPVklERVJfSUQnLFxuICBJTlZBTElEX1JFQ0lQSUVOVF9FTUFJTCA9ICdJTlZBTElEX1JFQ0lQSUVOVF9FTUFJTCcsXG4gIElOVkFMSURfU0VOREVSID0gJ0lOVkFMSURfU0VOREVSJyxcbiAgSU5WQUxJRF9TRVNTSU9OX0lORk8gPSAnSU5WQUxJRF9TRVNTSU9OX0lORk8nLFxuICBJTlZBTElEX1RFTVBPUkFSWV9QUk9PRiA9ICdJTlZBTElEX1RFTVBPUkFSWV9QUk9PRicsXG4gIElOVkFMSURfVEVOQU5UX0lEID0gJ0lOVkFMSURfVEVOQU5UX0lEJyxcbiAgTUZBX0VOUk9MTE1FTlRfTk9UX0ZPVU5EID0gJ01GQV9FTlJPTExNRU5UX05PVF9GT1VORCcsXG4gIE1JU1NJTkdfQU5EUk9JRF9QQUNLQUdFX05BTUUgPSAnTUlTU0lOR19BTkRST0lEX1BBQ0tBR0VfTkFNRScsXG4gIE1JU1NJTkdfQVBQX0NSRURFTlRJQUwgPSAnTUlTU0lOR19BUFBfQ1JFREVOVElBTCcsXG4gIE1JU1NJTkdfQ09ERSA9ICdNSVNTSU5HX0NPREUnLFxuICBNSVNTSU5HX0NPTlRJTlVFX1VSSSA9ICdNSVNTSU5HX0NPTlRJTlVFX1VSSScsXG4gIE1JU1NJTkdfQ1VTVE9NX1RPS0VOID0gJ01JU1NJTkdfQ1VTVE9NX1RPS0VOJyxcbiAgTUlTU0lOR19JT1NfQlVORExFX0lEID0gJ01JU1NJTkdfSU9TX0JVTkRMRV9JRCcsXG4gIE1JU1NJTkdfTUZBX0VOUk9MTE1FTlRfSUQgPSAnTUlTU0lOR19NRkFfRU5ST0xMTUVOVF9JRCcsXG4gIE1JU1NJTkdfTUZBX1BFTkRJTkdfQ1JFREVOVElBTCA9ICdNSVNTSU5HX01GQV9QRU5ESU5HX0NSRURFTlRJQUwnLFxuICBNSVNTSU5HX09PQl9DT0RFID0gJ01JU1NJTkdfT09CX0NPREUnLFxuICBNSVNTSU5HX09SX0lOVkFMSURfTk9OQ0UgPSAnTUlTU0lOR19PUl9JTlZBTElEX05PTkNFJyxcbiAgTUlTU0lOR19QQVNTV09SRCA9ICdNSVNTSU5HX1BBU1NXT1JEJyxcbiAgTUlTU0lOR19SRVFfVFlQRSA9ICdNSVNTSU5HX1JFUV9UWVBFJyxcbiAgTUlTU0lOR19QSE9ORV9OVU1CRVIgPSAnTUlTU0lOR19QSE9ORV9OVU1CRVInLFxuICBNSVNTSU5HX1NFU1NJT05fSU5GTyA9ICdNSVNTSU5HX1NFU1NJT05fSU5GTycsXG4gIE9QRVJBVElPTl9OT1RfQUxMT1dFRCA9ICdPUEVSQVRJT05fTk9UX0FMTE9XRUQnLFxuICBQQVNTV09SRF9MT0dJTl9ESVNBQkxFRCA9ICdQQVNTV09SRF9MT0dJTl9ESVNBQkxFRCcsXG4gIFFVT1RBX0VYQ0VFREVEID0gJ1FVT1RBX0VYQ0VFREVEJyxcbiAgUkVTRVRfUEFTU1dPUkRfRVhDRUVEX0xJTUlUID0gJ1JFU0VUX1BBU1NXT1JEX0VYQ0VFRF9MSU1JVCcsXG4gIFJFSkVDVEVEX0NSRURFTlRJQUwgPSAnUkVKRUNURURfQ1JFREVOVElBTCcsXG4gIFNFQ09ORF9GQUNUT1JfRVhJU1RTID0gJ1NFQ09ORF9GQUNUT1JfRVhJU1RTJyxcbiAgU0VDT05EX0ZBQ1RPUl9MSU1JVF9FWENFRURFRCA9ICdTRUNPTkRfRkFDVE9SX0xJTUlUX0VYQ0VFREVEJyxcbiAgU0VTU0lPTl9FWFBJUkVEID0gJ1NFU1NJT05fRVhQSVJFRCcsXG4gIFRFTkFOVF9JRF9NSVNNQVRDSCA9ICdURU5BTlRfSURfTUlTTUFUQ0gnLFxuICBUT0tFTl9FWFBJUkVEID0gJ1RPS0VOX0VYUElSRUQnLFxuICBUT09fTUFOWV9BVFRFTVBUU19UUllfTEFURVIgPSAnVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSJyxcbiAgVU5TVVBQT1JURURfRklSU1RfRkFDVE9SID0gJ1VOU1VQUE9SVEVEX0ZJUlNUX0ZBQ1RPUicsXG4gIFVOU1VQUE9SVEVEX1RFTkFOVF9PUEVSQVRJT04gPSAnVU5TVVBQT1JURURfVEVOQU5UX09QRVJBVElPTicsXG4gIFVOQVVUSE9SSVpFRF9ET01BSU4gPSAnVU5BVVRIT1JJWkVEX0RPTUFJTicsXG4gIFVOVkVSSUZJRURfRU1BSUwgPSAnVU5WRVJJRklFRF9FTUFJTCcsXG4gIFVTRVJfQ0FOQ0VMTEVEID0gJ1VTRVJfQ0FOQ0VMTEVEJyxcbiAgVVNFUl9ESVNBQkxFRCA9ICdVU0VSX0RJU0FCTEVEJyxcbiAgVVNFUl9OT1RfRk9VTkQgPSAnVVNFUl9OT1RfRk9VTkQnLFxuICBXRUFLX1BBU1NXT1JEID0gJ1dFQUtfUEFTU1dPUkQnLFxuICBSRUNBUFRDSEFfTk9UX0VOQUJMRUQgPSAnUkVDQVBUQ0hBX05PVF9FTkFCTEVEJyxcbiAgTUlTU0lOR19SRUNBUFRDSEFfVE9LRU4gPSAnTUlTU0lOR19SRUNBUFRDSEFfVE9LRU4nLFxuICBJTlZBTElEX1JFQ0FQVENIQV9UT0tFTiA9ICdJTlZBTElEX1JFQ0FQVENIQV9UT0tFTicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX0FDVElPTiA9ICdJTlZBTElEX1JFQ0FQVENIQV9BQ1RJT04nLFxuICBNSVNTSU5HX0NMSUVOVF9UWVBFID0gJ01JU1NJTkdfQ0xJRU5UX1RZUEUnLFxuICBNSVNTSU5HX1JFQ0FQVENIQV9WRVJTSU9OID0gJ01JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT04nLFxuICBJTlZBTElEX1JFQ0FQVENIQV9WRVJTSU9OID0gJ0lOVkFMSURfUkVDQVBUQ0hBX1ZFUlNJT04nLFxuICBJTlZBTElEX1JFUV9UWVBFID0gJ0lOVkFMSURfUkVRX1RZUEUnLFxuICBQQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UUyA9ICdQQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UUycsXG4gIElOVkFMSURfSE9TVElOR19MSU5LX0RPTUFJTiA9ICdJTlZBTElEX0hPU1RJTkdfTElOS19ET01BSU4nXG59XG5cbi8qKlxuICogQVBJIFJlc3BvbnNlIGluIHRoZSBldmVudCBvZiBhbiBlcnJvclxuICovXG5leHBvcnQgaW50ZXJmYWNlIEpzb25FcnJvciB7XG4gIGVycm9yOiB7XG4gICAgY29kZTogbnVtYmVyO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcbiAgICBlcnJvcnM/OiBbXG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6IFNlcnZlckVycm9yO1xuICAgICAgICBkb21haW46IHN0cmluZztcbiAgICAgICAgcmVhc29uOiBzdHJpbmc7XG4gICAgICB9XG4gICAgXTtcbiAgfTtcbn1cblxuLyoqXG4gKiBUeXBlIGRlZmluaXRpb24gZm9yIGEgbWFwIGZyb20gc2VydmVyIGVycm9ycyB0byBkZXZlbG9wZXIgdmlzaWJsZSBlcnJvcnNcbiAqL1xuZXhwb3J0IGRlY2xhcmUgdHlwZSBTZXJ2ZXJFcnJvck1hcDxBcGlFcnJvciBleHRlbmRzIHN0cmluZz4gPSB7XG4gIHJlYWRvbmx5IFtLIGluIEFwaUVycm9yXTogQXV0aEVycm9yQ29kZTtcbn07XG5cbi8qKlxuICogTWFwIGZyb20gZXJyb3JzIHJldHVybmVkIGJ5IHRoZSBzZXJ2ZXIgdG8gZXJyb3JzIHRvIGRldmVsb3BlciB2aXNpYmxlIGVycm9yc1xuICovXG5leHBvcnQgY29uc3QgU0VSVkVSX0VSUk9SX01BUDogUGFydGlhbDxTZXJ2ZXJFcnJvck1hcDxTZXJ2ZXJFcnJvcj4+ID0ge1xuICAvLyBDdXN0b20gdG9rZW4gZXJyb3JzLlxuICBbU2VydmVyRXJyb3IuQ1JFREVOVElBTF9NSVNNQVRDSF06IEF1dGhFcnJvckNvZGUuQ1JFREVOVElBTF9NSVNNQVRDSCxcbiAgLy8gVGhpcyBjYW4gb25seSBoYXBwZW4gaWYgdGhlIFNESyBzZW5kcyBhIGJhZCByZXF1ZXN0LlxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19DVVNUT01fVE9LRU5dOiBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuXG4gIC8vIENyZWF0ZSBBdXRoIFVSSSBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0lERU5USUZJRVJdOiBBdXRoRXJyb3JDb2RlLklOVkFMSURfRU1BSUwsXG4gIC8vIFRoaXMgY2FuIG9ubHkgaGFwcGVuIGlmIHRoZSBTREsgc2VuZHMgYSBiYWQgcmVxdWVzdC5cbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfQ09OVElOVUVfVVJJXTogQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUixcblxuICAvLyBTaWduIGluIHdpdGggZW1haWwgYW5kIHBhc3N3b3JkIGVycm9ycyAoc29tZSBhcHBseSB0byBzaWduIHVwIHRvbykuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX1BBU1NXT1JEXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX1BBU1NXT1JELFxuICAvLyBUaGlzIGNhbiBvbmx5IGhhcHBlbiBpZiB0aGUgU0RLIHNlbmRzIGEgYmFkIHJlcXVlc3QuXG4gIFtTZXJ2ZXJFcnJvci5NSVNTSU5HX1BBU1NXT1JEXTogQXV0aEVycm9yQ29kZS5NSVNTSU5HX1BBU1NXT1JELFxuICAvLyBUaHJvd24gaWYgRW1haWwgRW51bWVyYXRpb24gUHJvdGVjdGlvbiBpcyBlbmFibGVkIGluIHRoZSBwcm9qZWN0IGFuZCB0aGUgZW1haWwgb3IgcGFzc3dvcmQgaXNcbiAgLy8gaW52YWxpZC5cbiAgW1NlcnZlckVycm9yLklOVkFMSURfTE9HSU5fQ1JFREVOVElBTFNdOiBBdXRoRXJyb3JDb2RlLklOVkFMSURfQ1JFREVOVElBTCxcblxuICAvLyBTaWduIHVwIHdpdGggZW1haWwgYW5kIHBhc3N3b3JkIGVycm9ycy5cbiAgW1NlcnZlckVycm9yLkVNQUlMX0VYSVNUU106IEF1dGhFcnJvckNvZGUuRU1BSUxfRVhJU1RTLFxuICBbU2VydmVyRXJyb3IuUEFTU1dPUkRfTE9HSU5fRElTQUJMRURdOiBBdXRoRXJyb3JDb2RlLk9QRVJBVElPTl9OT1RfQUxMT1dFRCxcblxuICAvLyBWZXJpZnkgYXNzZXJ0aW9uIGZvciBzaWduIGluIHdpdGggY3JlZGVudGlhbCBlcnJvcnM6XG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0lEUF9SRVNQT05TRV06IEF1dGhFcnJvckNvZGUuSU5WQUxJRF9DUkVERU5USUFMLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9QRU5ESU5HX1RPS0VOXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX0NSRURFTlRJQUwsXG4gIFtTZXJ2ZXJFcnJvci5GRURFUkFURURfVVNFUl9JRF9BTFJFQURZX0xJTktFRF06XG4gICAgQXV0aEVycm9yQ29kZS5DUkVERU5USUFMX0FMUkVBRFlfSU5fVVNFLFxuXG4gIC8vIFRoaXMgY2FuIG9ubHkgaGFwcGVuIGlmIHRoZSBTREsgc2VuZHMgYSBiYWQgcmVxdWVzdC5cbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfUkVRX1RZUEVdOiBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuXG4gIC8vIFNlbmQgUGFzc3dvcmQgcmVzZXQgZW1haWwgZXJyb3JzOlxuICBbU2VydmVyRXJyb3IuRU1BSUxfTk9UX0ZPVU5EXTogQXV0aEVycm9yQ29kZS5VU0VSX0RFTEVURUQsXG4gIFtTZXJ2ZXJFcnJvci5SRVNFVF9QQVNTV09SRF9FWENFRURfTElNSVRdOlxuICAgIEF1dGhFcnJvckNvZGUuVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSLFxuXG4gIFtTZXJ2ZXJFcnJvci5FWFBJUkVEX09PQl9DT0RFXTogQXV0aEVycm9yQ29kZS5FWFBJUkVEX09PQl9DT0RFLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9PT0JfQ09ERV06IEF1dGhFcnJvckNvZGUuSU5WQUxJRF9PT0JfQ09ERSxcbiAgLy8gVGhpcyBjYW4gb25seSBoYXBwZW4gaWYgdGhlIFNESyBzZW5kcyBhIGJhZCByZXF1ZXN0LlxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19PT0JfQ09ERV06IEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IsXG5cbiAgLy8gT3BlcmF0aW9ucyB0aGF0IHJlcXVpcmUgSUQgdG9rZW4gaW4gcmVxdWVzdDpcbiAgW1NlcnZlckVycm9yLkNSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTl06XG4gICAgQXV0aEVycm9yQ29kZS5DUkVERU5USUFMX1RPT19PTERfTE9HSU5fQUdBSU4sXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0lEX1RPS0VOXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX0FVVEgsXG4gIFtTZXJ2ZXJFcnJvci5UT0tFTl9FWFBJUkVEXTogQXV0aEVycm9yQ29kZS5UT0tFTl9FWFBJUkVELFxuICBbU2VydmVyRXJyb3IuVVNFUl9OT1RfRk9VTkRdOiBBdXRoRXJyb3JDb2RlLlRPS0VOX0VYUElSRUQsXG5cbiAgLy8gT3RoZXIgZXJyb3JzLlxuICBbU2VydmVyRXJyb3IuVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSXTpcbiAgICBBdXRoRXJyb3JDb2RlLlRPT19NQU5ZX0FUVEVNUFRTX1RSWV9MQVRFUixcbiAgW1NlcnZlckVycm9yLlBBU1NXT1JEX0RPRVNfTk9UX01FRVRfUkVRVUlSRU1FTlRTXTpcbiAgICBBdXRoRXJyb3JDb2RlLlBBU1NXT1JEX0RPRVNfTk9UX01FRVRfUkVRVUlSRU1FTlRTLFxuXG4gIC8vIFBob25lIEF1dGggcmVsYXRlZCBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0NPREVdOiBBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09ERSxcbiAgW1NlcnZlckVycm9yLklOVkFMSURfU0VTU0lPTl9JTkZPXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX1NFU1NJT05fSU5GTyxcbiAgW1NlcnZlckVycm9yLklOVkFMSURfVEVNUE9SQVJZX1BST09GXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX0NSRURFTlRJQUwsXG4gIFtTZXJ2ZXJFcnJvci5NSVNTSU5HX1NFU1NJT05fSU5GT106IEF1dGhFcnJvckNvZGUuTUlTU0lOR19TRVNTSU9OX0lORk8sXG4gIFtTZXJ2ZXJFcnJvci5TRVNTSU9OX0VYUElSRURdOiBBdXRoRXJyb3JDb2RlLkNPREVfRVhQSVJFRCxcblxuICAvLyBPdGhlciBhY3Rpb24gY29kZSBlcnJvcnMgd2hlbiBhZGRpdGlvbmFsIHNldHRpbmdzIHBhc3NlZC5cbiAgLy8gTUlTU0lOR19DT05USU5VRV9VUkkgaXMgZ2V0dGluZyBtYXBwZWQgdG8gSU5URVJOQUxfRVJST1IgYWJvdmUuXG4gIC8vIFRoaXMgaXMgT0sgYXMgdGhpcyBlcnJvciB3aWxsIGJlIGNhdWdodCBieSBjbGllbnQgc2lkZSB2YWxpZGF0aW9uLlxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19BTkRST0lEX1BBQ0tBR0VfTkFNRV06XG4gICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX0FORFJPSURfUEFDS0FHRV9OQU1FLFxuICBbU2VydmVyRXJyb3IuVU5BVVRIT1JJWkVEX0RPTUFJTl06IEF1dGhFcnJvckNvZGUuVU5BVVRIT1JJWkVEX0RPTUFJTixcblxuICAvLyBnZXRQcm9qZWN0Q29uZmlnIGVycm9ycyB3aGVuIGNsaWVudElkIGlzIHBhc3NlZC5cbiAgW1NlcnZlckVycm9yLklOVkFMSURfT0FVVEhfQ0xJRU5UX0lEXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX09BVVRIX0NMSUVOVF9JRCxcblxuICAvLyBVc2VyIGFjdGlvbnMgKHNpZ24tdXAgb3IgZGVsZXRpb24pIGRpc2FibGVkIGVycm9ycy5cbiAgW1NlcnZlckVycm9yLkFETUlOX09OTFlfT1BFUkFUSU9OXTogQXV0aEVycm9yQ29kZS5BRE1JTl9PTkxZX09QRVJBVElPTixcblxuICAvLyBNdWx0aSBmYWN0b3IgcmVsYXRlZCBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX01GQV9QRU5ESU5HX0NSRURFTlRJQUxdOlxuICAgIEF1dGhFcnJvckNvZGUuSU5WQUxJRF9NRkFfU0VTU0lPTixcbiAgW1NlcnZlckVycm9yLk1GQV9FTlJPTExNRU5UX05PVF9GT1VORF06IEF1dGhFcnJvckNvZGUuTUZBX0lORk9fTk9UX0ZPVU5ELFxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19NRkFfRU5ST0xMTUVOVF9JRF06IEF1dGhFcnJvckNvZGUuTUlTU0lOR19NRkFfSU5GTyxcbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfTUZBX1BFTkRJTkdfQ1JFREVOVElBTF06XG4gICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX01GQV9TRVNTSU9OLFxuICBbU2VydmVyRXJyb3IuU0VDT05EX0ZBQ1RPUl9FWElTVFNdOlxuICAgIEF1dGhFcnJvckNvZGUuU0VDT05EX0ZBQ1RPUl9BTFJFQURZX0VOUk9MTEVELFxuICBbU2VydmVyRXJyb3IuU0VDT05EX0ZBQ1RPUl9MSU1JVF9FWENFRURFRF06XG4gICAgQXV0aEVycm9yQ29kZS5TRUNPTkRfRkFDVE9SX0xJTUlUX0VYQ0VFREVELFxuXG4gIC8vIEJsb2NraW5nIGZ1bmN0aW9ucyByZWxhdGVkIGVycm9ycy5cbiAgW1NlcnZlckVycm9yLkJMT0NLSU5HX0ZVTkNUSU9OX0VSUk9SX1JFU1BPTlNFXTogQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUixcblxuICAvLyBSZWNhcHRjaGEgcmVsYXRlZCBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5SRUNBUFRDSEFfTk9UX0VOQUJMRURdOiBBdXRoRXJyb3JDb2RlLlJFQ0FQVENIQV9OT1RfRU5BQkxFRCxcbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfUkVDQVBUQ0hBX1RPS0VOXTogQXV0aEVycm9yQ29kZS5NSVNTSU5HX1JFQ0FQVENIQV9UT0tFTixcbiAgW1NlcnZlckVycm9yLklOVkFMSURfUkVDQVBUQ0hBX1RPS0VOXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0FQVENIQV9UT0tFTixcbiAgW1NlcnZlckVycm9yLklOVkFMSURfUkVDQVBUQ0hBX0FDVElPTl06XG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0FQVENIQV9BQ1RJT04sXG4gIFtTZXJ2ZXJFcnJvci5NSVNTSU5HX0NMSUVOVF9UWVBFXTogQXV0aEVycm9yQ29kZS5NSVNTSU5HX0NMSUVOVF9UWVBFLFxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19SRUNBUFRDSEFfVkVSU0lPTl06XG4gICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX1JFQ0FQVENIQV9WRVJTSU9OLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9SRUNBUFRDSEFfVkVSU0lPTl06XG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0FQVENIQV9WRVJTSU9OLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9SRVFfVFlQRV06IEF1dGhFcnJvckNvZGUuSU5WQUxJRF9SRVFfVFlQRVxufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBGaXJlYmFzZUVycm9yLFxuICBpc0Nsb3VkZmxhcmVXb3JrZXIsXG4gIGlzQ2xvdWRXb3Jrc3RhdGlvbixcbiAgcXVlcnlzdHJpbmdcbn0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlLCBOYW1lZEVycm9yUGFyYW1zIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgX2NyZWF0ZUVycm9yLFxuICBfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZSxcbiAgX2ZhaWxcbn0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBEZWxheSB9IGZyb20gJy4uL2NvcmUvdXRpbC9kZWxheSc7XG5pbXBvcnQgeyBfZW11bGF0b3JVcmwgfSBmcm9tICcuLi9jb3JlL3V0aWwvZW11bGF0b3InO1xuaW1wb3J0IHsgRmV0Y2hQcm92aWRlciB9IGZyb20gJy4uL2NvcmUvdXRpbC9mZXRjaF9wcm92aWRlcic7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCwgQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSwgVGFnZ2VkV2l0aFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBJZFRva2VuTWZhUmVzcG9uc2UgfSBmcm9tICcuL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBTRVJWRVJfRVJST1JfTUFQLCBTZXJ2ZXJFcnJvciwgU2VydmVyRXJyb3JNYXAgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBQZXJzaXN0ZW5jZVR5cGUgfSBmcm9tICcuLi9jb3JlL3BlcnNpc3RlbmNlJztcbmltcG9ydCB7IENvb2tpZVBlcnNpc3RlbmNlIH0gZnJvbSAnLi4vcGxhdGZvcm1fYnJvd3Nlci9wZXJzaXN0ZW5jZS9jb29raWVfc3RvcmFnZSc7XG5cbmV4cG9ydCBjb25zdCBlbnVtIEh0dHBNZXRob2Qge1xuICBQT1NUID0gJ1BPU1QnLFxuICBHRVQgPSAnR0VUJ1xufVxuXG5leHBvcnQgY29uc3QgZW51bSBIdHRwSGVhZGVyIHtcbiAgQ09OVEVOVF9UWVBFID0gJ0NvbnRlbnQtVHlwZScsXG4gIFhfRklSRUJBU0VfTE9DQUxFID0gJ1gtRmlyZWJhc2UtTG9jYWxlJyxcbiAgWF9DTElFTlRfVkVSU0lPTiA9ICdYLUNsaWVudC1WZXJzaW9uJyxcbiAgWF9GSVJFQkFTRV9HTVBJRCA9ICdYLUZpcmViYXNlLWdtcGlkJyxcbiAgWF9GSVJFQkFTRV9DTElFTlQgPSAnWC1GaXJlYmFzZS1DbGllbnQnLFxuICBYX0ZJUkVCQVNFX0FQUF9DSEVDSyA9ICdYLUZpcmViYXNlLUFwcENoZWNrJ1xufVxuXG5leHBvcnQgY29uc3QgZW51bSBFbmRwb2ludCB7XG4gIENSRUFURV9BVVRIX1VSSSA9ICcvdjEvYWNjb3VudHM6Y3JlYXRlQXV0aFVyaScsXG4gIERFTEVURV9BQ0NPVU5UID0gJy92MS9hY2NvdW50czpkZWxldGUnLFxuICBSRVNFVF9QQVNTV09SRCA9ICcvdjEvYWNjb3VudHM6cmVzZXRQYXNzd29yZCcsXG4gIFNJR05fVVAgPSAnL3YxL2FjY291bnRzOnNpZ25VcCcsXG4gIFNJR05fSU5fV0lUSF9DVVNUT01fVE9LRU4gPSAnL3YxL2FjY291bnRzOnNpZ25JbldpdGhDdXN0b21Ub2tlbicsXG4gIFNJR05fSU5fV0lUSF9FTUFJTF9MSU5LID0gJy92MS9hY2NvdW50czpzaWduSW5XaXRoRW1haWxMaW5rJyxcbiAgU0lHTl9JTl9XSVRIX0lEUCA9ICcvdjEvYWNjb3VudHM6c2lnbkluV2l0aElkcCcsXG4gIFNJR05fSU5fV0lUSF9QQVNTV09SRCA9ICcvdjEvYWNjb3VudHM6c2lnbkluV2l0aFBhc3N3b3JkJyxcbiAgU0lHTl9JTl9XSVRIX1BIT05FX05VTUJFUiA9ICcvdjEvYWNjb3VudHM6c2lnbkluV2l0aFBob25lTnVtYmVyJyxcbiAgU0VORF9WRVJJRklDQVRJT05fQ09ERSA9ICcvdjEvYWNjb3VudHM6c2VuZFZlcmlmaWNhdGlvbkNvZGUnLFxuICBTRU5EX09PQl9DT0RFID0gJy92MS9hY2NvdW50czpzZW5kT29iQ29kZScsXG4gIFNFVF9BQ0NPVU5UX0lORk8gPSAnL3YxL2FjY291bnRzOnVwZGF0ZScsXG4gIEdFVF9BQ0NPVU5UX0lORk8gPSAnL3YxL2FjY291bnRzOmxvb2t1cCcsXG4gIEdFVF9SRUNBUFRDSEFfUEFSQU0gPSAnL3YxL3JlY2FwdGNoYVBhcmFtcycsXG4gIFNUQVJUX01GQV9FTlJPTExNRU5UID0gJy92Mi9hY2NvdW50cy9tZmFFbnJvbGxtZW50OnN0YXJ0JyxcbiAgRklOQUxJWkVfTUZBX0VOUk9MTE1FTlQgPSAnL3YyL2FjY291bnRzL21mYUVucm9sbG1lbnQ6ZmluYWxpemUnLFxuICBTVEFSVF9NRkFfU0lHTl9JTiA9ICcvdjIvYWNjb3VudHMvbWZhU2lnbkluOnN0YXJ0JyxcbiAgRklOQUxJWkVfTUZBX1NJR05fSU4gPSAnL3YyL2FjY291bnRzL21mYVNpZ25JbjpmaW5hbGl6ZScsXG4gIFdJVEhEUkFXX01GQSA9ICcvdjIvYWNjb3VudHMvbWZhRW5yb2xsbWVudDp3aXRoZHJhdycsXG4gIEdFVF9QUk9KRUNUX0NPTkZJRyA9ICcvdjEvcHJvamVjdHMnLFxuICBHRVRfUkVDQVBUQ0hBX0NPTkZJRyA9ICcvdjIvcmVjYXB0Y2hhQ29uZmlnJyxcbiAgR0VUX1BBU1NXT1JEX1BPTElDWSA9ICcvdjIvcGFzc3dvcmRQb2xpY3knLFxuICBUT0tFTiA9ICcvdjEvdG9rZW4nLFxuICBSRVZPS0VfVE9LRU4gPSAnL3YyL2FjY291bnRzOnJldm9rZVRva2VuJ1xufVxuXG5jb25zdCBDb29raWVBdXRoUHJveGllZEVuZHBvaW50czogc3RyaW5nW10gPSBbXG4gIEVuZHBvaW50LlNJR05fSU5fV0lUSF9DVVNUT01fVE9LRU4sXG4gIEVuZHBvaW50LlNJR05fSU5fV0lUSF9FTUFJTF9MSU5LLFxuICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfSURQLFxuICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfUEFTU1dPUkQsXG4gIEVuZHBvaW50LlNJR05fSU5fV0lUSF9QSE9ORV9OVU1CRVIsXG4gIEVuZHBvaW50LlRPS0VOXG5dO1xuXG5leHBvcnQgY29uc3QgZW51bSBSZWNhcHRjaGFDbGllbnRUeXBlIHtcbiAgV0VCID0gJ0NMSUVOVF9UWVBFX1dFQicsXG4gIEFORFJPSUQgPSAnQ0xJRU5UX1RZUEVfQU5EUk9JRCcsXG4gIElPUyA9ICdDTElFTlRfVFlQRV9JT1MnXG59XG5cbmV4cG9ydCBjb25zdCBlbnVtIFJlY2FwdGNoYVZlcnNpb24ge1xuICBFTlRFUlBSSVNFID0gJ1JFQ0FQVENIQV9FTlRFUlBSSVNFJ1xufVxuXG5leHBvcnQgY29uc3QgZW51bSBSZWNhcHRjaGFBY3Rpb25OYW1lIHtcbiAgU0lHTl9JTl9XSVRIX1BBU1NXT1JEID0gJ3NpZ25JbldpdGhQYXNzd29yZCcsXG4gIEdFVF9PT0JfQ09ERSA9ICdnZXRPb2JDb2RlJyxcbiAgU0lHTl9VUF9QQVNTV09SRCA9ICdzaWduVXBQYXNzd29yZCcsXG4gIFNFTkRfVkVSSUZJQ0FUSU9OX0NPREUgPSAnc2VuZFZlcmlmaWNhdGlvbkNvZGUnLFxuICBNRkFfU01TX0VOUk9MTE1FTlQgPSAnbWZhU21zRW5yb2xsbWVudCcsXG4gIE1GQV9TTVNfU0lHTklOID0gJ21mYVNtc1NpZ25Jbidcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gRW5mb3JjZW1lbnRTdGF0ZSB7XG4gIEVORk9SQ0UgPSAnRU5GT1JDRScsXG4gIEFVRElUID0gJ0FVRElUJyxcbiAgT0ZGID0gJ09GRicsXG4gIEVORk9SQ0VNRU5UX1NUQVRFX1VOU1BFQ0lGSUVEID0gJ0VORk9SQ0VNRU5UX1NUQVRFX1VOU1BFQ0lGSUVEJ1xufVxuXG4vLyBQcm92aWRlcnMgdGhhdCBoYXZlIHJlQ0FQVENIQSBFbnRlcnByaXNlIHN1cHBvcnQuXG5leHBvcnQgY29uc3QgZW51bSBSZWNhcHRjaGFBdXRoUHJvdmlkZXIge1xuICBFTUFJTF9QQVNTV09SRF9QUk9WSURFUiA9ICdFTUFJTF9QQVNTV09SRF9QUk9WSURFUicsXG4gIFBIT05FX1BST1ZJREVSID0gJ1BIT05FX1BST1ZJREVSJ1xufVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9BUElfVElNRU9VVF9NUyA9IG5ldyBEZWxheSgzMF8wMDAsIDYwXzAwMCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBfYWRkVGlkSWZOZWNlc3Nhcnk8VCBleHRlbmRzIHsgdGVuYW50SWQ/OiBzdHJpbmcgfT4oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFRcbik6IFQge1xuICBpZiAoYXV0aC50ZW5hbnRJZCAmJiAhcmVxdWVzdC50ZW5hbnRJZCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5yZXF1ZXN0LFxuICAgICAgdGVuYW50SWQ6IGF1dGgudGVuYW50SWRcbiAgICB9O1xuICB9XG4gIHJldHVybiByZXF1ZXN0O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX3BlcmZvcm1BcGlSZXF1ZXN0PFQsIFY+KFxuICBhdXRoOiBBdXRoLFxuICBtZXRob2Q6IEh0dHBNZXRob2QsXG4gIHBhdGg6IEVuZHBvaW50LFxuICByZXF1ZXN0PzogVCxcbiAgY3VzdG9tRXJyb3JNYXA6IFBhcnRpYWw8U2VydmVyRXJyb3JNYXA8U2VydmVyRXJyb3I+PiA9IHt9XG4pOiBQcm9taXNlPFY+IHtcbiAgcmV0dXJuIF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZyhhdXRoLCBjdXN0b21FcnJvck1hcCwgYXN5bmMgKCkgPT4ge1xuICAgIGxldCBib2R5ID0ge307XG4gICAgbGV0IHBhcmFtcyA9IHt9O1xuICAgIGlmIChyZXF1ZXN0KSB7XG4gICAgICBpZiAobWV0aG9kID09PSBIdHRwTWV0aG9kLkdFVCkge1xuICAgICAgICBwYXJhbXMgPSByZXF1ZXN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYm9keSA9IHtcbiAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5ID0gcXVlcnlzdHJpbmcoe1xuICAgICAga2V5OiBhdXRoLmNvbmZpZy5hcGlLZXksXG4gICAgICAuLi5wYXJhbXNcbiAgICB9KS5zbGljZSgxKTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSBhd2FpdCAoYXV0aCBhcyBBdXRoSW50ZXJuYWwpLl9nZXRBZGRpdGlvbmFsSGVhZGVycygpO1xuICAgIGhlYWRlcnNbSHR0cEhlYWRlci5DT05URU5UX1RZUEVdID0gJ2FwcGxpY2F0aW9uL2pzb24nO1xuXG4gICAgaWYgKGF1dGgubGFuZ3VhZ2VDb2RlKSB7XG4gICAgICBoZWFkZXJzW0h0dHBIZWFkZXIuWF9GSVJFQkFTRV9MT0NBTEVdID0gYXV0aC5sYW5ndWFnZUNvZGU7XG4gICAgfVxuXG4gICAgY29uc3QgZmV0Y2hBcmdzOiBSZXF1ZXN0SW5pdCA9IHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIGhlYWRlcnMsXG4gICAgICAuLi5ib2R5XG4gICAgfTtcblxuICAgIC8qIFNlY3VyaXR5LWNvbnNjaW91cyBzZXJ2ZXItc2lkZSBmcmFtZXdvcmtzIHRlbmQgdG8gaGF2ZSBidWlsdCBpbiBtaXRpZ2F0aW9ucyBmb3IgcmVmZXJyZXJcbiAgICAgICBwcm9ibGVtc1wiLiBTZWUgdGhlIENsb3VkZmxhcmUgR2l0SHViIGlzc3VlICM0ODc6IEVycm9yOiBUaGUgJ3JlZmVycmVyUG9saWN5JyBmaWVsZCBvblxuICAgICAgICdSZXF1ZXN0SW5pdGlhbGl6ZXJEaWN0JyBpcyBub3QgaW1wbGVtZW50ZWQuXCJcbiAgICAgICBodHRwczovL2dpdGh1Yi5jb20vY2xvdWRmbGFyZS9uZXh0LW9uLXBhZ2VzL2lzc3Vlcy80ODcgKi9cbiAgICBpZiAoIWlzQ2xvdWRmbGFyZVdvcmtlcigpKSB7XG4gICAgICBmZXRjaEFyZ3MucmVmZXJyZXJQb2xpY3kgPSAnbm8tcmVmZXJyZXInO1xuICAgIH1cblxuICAgIGlmIChhdXRoLmVtdWxhdG9yQ29uZmlnICYmIGlzQ2xvdWRXb3Jrc3RhdGlvbihhdXRoLmVtdWxhdG9yQ29uZmlnLmhvc3QpKSB7XG4gICAgICBmZXRjaEFyZ3MuY3JlZGVudGlhbHMgPSAnaW5jbHVkZSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIEZldGNoUHJvdmlkZXIuZmV0Y2goKShcbiAgICAgIGF3YWl0IF9nZXRGaW5hbFRhcmdldChhdXRoLCBhdXRoLmNvbmZpZy5hcGlIb3N0LCBwYXRoLCBxdWVyeSksXG4gICAgICBmZXRjaEFyZ3NcbiAgICApO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZzxWPihcbiAgYXV0aDogQXV0aCxcbiAgY3VzdG9tRXJyb3JNYXA6IFBhcnRpYWw8U2VydmVyRXJyb3JNYXA8U2VydmVyRXJyb3I+PixcbiAgZmV0Y2hGbjogKCkgPT4gUHJvbWlzZTxSZXNwb25zZT5cbik6IFByb21pc2U8Vj4ge1xuICAoYXV0aCBhcyBBdXRoSW50ZXJuYWwpLl9jYW5Jbml0RW11bGF0b3IgPSBmYWxzZTtcbiAgY29uc3QgZXJyb3JNYXAgPSB7IC4uLlNFUlZFUl9FUlJPUl9NQVAsIC4uLmN1c3RvbUVycm9yTWFwIH07XG4gIHRyeSB7XG4gICAgY29uc3QgbmV0d29ya1RpbWVvdXQgPSBuZXcgTmV0d29ya1RpbWVvdXQ8UmVzcG9uc2U+KGF1dGgpO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBSZXNwb25zZSA9IGF3YWl0IFByb21pc2UucmFjZTxQcm9taXNlPFJlc3BvbnNlPj4oW1xuICAgICAgZmV0Y2hGbigpLFxuICAgICAgbmV0d29ya1RpbWVvdXQucHJvbWlzZVxuICAgIF0pO1xuXG4gICAgLy8gSWYgd2UndmUgcmVhY2hlZCB0aGlzIHBvaW50LCB0aGUgZmV0Y2ggc3VjY2VlZGVkIGFuZCB0aGUgbmV0d29ya1RpbWVvdXRcbiAgICAvLyBkaWRuJ3QgdGhyb3c7IGNsZWFyIHRoZSBuZXR3b3JrIHRpbWVvdXQgZGVsYXkgc28gdGhhdCBOb2RlIHdvbid0IGhhbmdcbiAgICBuZXR3b3JrVGltZW91dC5jbGVhck5ldHdvcmtUaW1lb3V0KCk7XG5cbiAgICBjb25zdCBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIGlmICgnbmVlZENvbmZpcm1hdGlvbicgaW4ganNvbikge1xuICAgICAgdGhyb3cgX21ha2VUYWdnZWRFcnJvcihhdXRoLCBBdXRoRXJyb3JDb2RlLk5FRURfQ09ORklSTUFUSU9OLCBqc29uKTtcbiAgICB9XG5cbiAgICBpZiAocmVzcG9uc2Uub2sgJiYgISgnZXJyb3JNZXNzYWdlJyBpbiBqc29uKSkge1xuICAgICAgcmV0dXJuIGpzb247XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IHJlc3BvbnNlLm9rID8ganNvbi5lcnJvck1lc3NhZ2UgOiBqc29uLmVycm9yLm1lc3NhZ2U7XG4gICAgICBjb25zdCBbc2VydmVyRXJyb3JDb2RlLCBzZXJ2ZXJFcnJvck1lc3NhZ2VdID0gZXJyb3JNZXNzYWdlLnNwbGl0KCcgOiAnKTtcbiAgICAgIGlmIChzZXJ2ZXJFcnJvckNvZGUgPT09IFNlcnZlckVycm9yLkZFREVSQVRFRF9VU0VSX0lEX0FMUkVBRFlfTElOS0VEKSB7XG4gICAgICAgIHRocm93IF9tYWtlVGFnZ2VkRXJyb3IoXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICBBdXRoRXJyb3JDb2RlLkNSRURFTlRJQUxfQUxSRUFEWV9JTl9VU0UsXG4gICAgICAgICAganNvblxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZXJ2ZXJFcnJvckNvZGUgPT09IFNlcnZlckVycm9yLkVNQUlMX0VYSVNUUykge1xuICAgICAgICB0aHJvdyBfbWFrZVRhZ2dlZEVycm9yKGF1dGgsIEF1dGhFcnJvckNvZGUuRU1BSUxfRVhJU1RTLCBqc29uKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VydmVyRXJyb3JDb2RlID09PSBTZXJ2ZXJFcnJvci5VU0VSX0RJU0FCTEVEKSB7XG4gICAgICAgIHRocm93IF9tYWtlVGFnZ2VkRXJyb3IoYXV0aCwgQXV0aEVycm9yQ29kZS5VU0VSX0RJU0FCTEVELCBqc29uKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF1dGhFcnJvciA9XG4gICAgICAgIGVycm9yTWFwW3NlcnZlckVycm9yQ29kZSBhcyBTZXJ2ZXJFcnJvcl0gfHxcbiAgICAgICAgKHNlcnZlckVycm9yQ29kZVxuICAgICAgICAgIC50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgLnJlcGxhY2UoL1tfXFxzXSsvZywgJy0nKSBhcyB1bmtub3duIGFzIEF1dGhFcnJvckNvZGUpO1xuICAgICAgaWYgKHNlcnZlckVycm9yTWVzc2FnZSkge1xuICAgICAgICB0aHJvdyBfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZShhdXRoLCBhdXRoRXJyb3IsIHNlcnZlckVycm9yTWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfZmFpbChhdXRoLCBhdXRoRXJyb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgRmlyZWJhc2VFcnJvcikge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgLy8gQ2hhbmdpbmcgdGhpcyB0byBhIGRpZmZlcmVudCBlcnJvciBjb2RlIHdpbGwgbG9nIHVzZXIgb3V0IHdoZW4gdGhlcmUgaXMgYSBuZXR3b3JrIGVycm9yXG4gICAgLy8gYmVjYXVzZSB3ZSB0cmVhdCBhbnkgZXJyb3Igb3RoZXIgdGhhbiBORVRXT1JLX1JFUVVFU1RfRkFJTEVEIGFzIHRva2VuIGlzIGludmFsaWQuXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2ZpcmViYXNlL2ZpcmViYXNlLWpzLXNkay9ibG9iLzRmYmM3MzYxMGQ3MGJlNGUwODUyZTdkZTYzYTM5Y2I3ODk3ZTg1NDYvcGFja2FnZXMvYXV0aC9zcmMvY29yZS9hdXRoL2F1dGhfaW1wbC50cyNMMzA5LUwzMTZcbiAgICBfZmFpbChhdXRoLCBBdXRoRXJyb3JDb2RlLk5FVFdPUktfUkVRVUVTVF9GQUlMRUQsIHsgJ21lc3NhZ2UnOiBTdHJpbmcoZSkgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9wZXJmb3JtU2lnbkluUmVxdWVzdDxULCBWIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlPihcbiAgYXV0aDogQXV0aCxcbiAgbWV0aG9kOiBIdHRwTWV0aG9kLFxuICBwYXRoOiBFbmRwb2ludCxcbiAgcmVxdWVzdD86IFQsXG4gIGN1c3RvbUVycm9yTWFwOiBQYXJ0aWFsPFNlcnZlckVycm9yTWFwPFNlcnZlckVycm9yPj4gPSB7fVxuKTogUHJvbWlzZTxWPiB7XG4gIGNvbnN0IHNlcnZlclJlc3BvbnNlID0gYXdhaXQgX3BlcmZvcm1BcGlSZXF1ZXN0PFQsIFYgfCBJZFRva2VuTWZhUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgbWV0aG9kLFxuICAgIHBhdGgsXG4gICAgcmVxdWVzdCxcbiAgICBjdXN0b21FcnJvck1hcFxuICApO1xuICBpZiAoJ21mYVBlbmRpbmdDcmVkZW50aWFsJyBpbiBzZXJ2ZXJSZXNwb25zZSkge1xuICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVELCB7XG4gICAgICBfc2VydmVyUmVzcG9uc2U6IHNlcnZlclJlc3BvbnNlXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc2VydmVyUmVzcG9uc2UgYXMgVjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9nZXRGaW5hbFRhcmdldChcbiAgYXV0aDogQXV0aCxcbiAgaG9zdDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIHF1ZXJ5OiBzdHJpbmdcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGJhc2UgPSBgJHtob3N0fSR7cGF0aH0/JHtxdWVyeX1gO1xuXG4gIGNvbnN0IGF1dGhJbnRlcm5hbCA9IGF1dGggYXMgQXV0aEludGVybmFsO1xuICBjb25zdCBmaW5hbFRhcmdldCA9IGF1dGhJbnRlcm5hbC5jb25maWcuZW11bGF0b3JcbiAgICA/IF9lbXVsYXRvclVybChhdXRoLmNvbmZpZyBhcyBDb25maWdJbnRlcm5hbCwgYmFzZSlcbiAgICA6IGAke2F1dGguY29uZmlnLmFwaVNjaGVtZX06Ly8ke2Jhc2V9YDtcblxuICAvLyBDb29raWUgYXV0aCB3b3JrcyBieSBNaVRNaW5nIHRoZSBzaWduSW4gYW5kIHRva2VuIGVuZHBvaW50cyBmcm9tIHRoZSBkZXZlbG9wZXIncyBiYWNrZW5kLFxuICAvLyBzYXZpbmcgdGhlIGlkVG9rZW4gYW5kIHJlZnJlc2hUb2tlbiBpbnRvIGNvb2tpZXMsIGFuZCB0aGVuIHJlZGFjdGluZyB0aGUgcmVmcmVzaFRva2VuXG4gIC8vIGZyb20gdGhlIHJlc3BvbnNlXG4gIGlmIChDb29raWVBdXRoUHJveGllZEVuZHBvaW50cy5pbmNsdWRlcyhwYXRoKSkge1xuICAgIC8vIFBlcnNpc3RlbmNlIG1hbmFnZXIgaXMgYXN5bmMsIHdlIG5lZWQgdG8gYXdhaXQgaXQuIFdlIGNhbid0IGp1c3Qgd2FpdCBmb3IgYXV0aCBpbml0aWFsaXplZFxuICAgIC8vIGhlcmUgc2luY2UgYXV0aCBpbml0aWFsaXphdGlvbiBjYWxscyB0aGlzIGZ1bmN0aW9uLlxuICAgIGF3YWl0IGF1dGhJbnRlcm5hbC5fcGVyc2lzdGVuY2VNYW5hZ2VyQXZhaWxhYmxlO1xuICAgIGlmIChhdXRoSW50ZXJuYWwuX2dldFBlcnNpc3RlbmNlVHlwZSgpID09PSBQZXJzaXN0ZW5jZVR5cGUuQ09PS0lFKSB7XG4gICAgICBjb25zdCBjb29raWVQZXJzaXN0ZW5jZSA9XG4gICAgICAgIGF1dGhJbnRlcm5hbC5fZ2V0UGVyc2lzdGVuY2UoKSBhcyBDb29raWVQZXJzaXN0ZW5jZTtcbiAgICAgIHJldHVybiBjb29raWVQZXJzaXN0ZW5jZS5fZ2V0RmluYWxUYXJnZXQoZmluYWxUYXJnZXQpLnRvU3RyaW5nKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZpbmFsVGFyZ2V0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3BhcnNlRW5mb3JjZW1lbnRTdGF0ZShcbiAgZW5mb3JjZW1lbnRTdGF0ZVN0cjogc3RyaW5nXG4pOiBFbmZvcmNlbWVudFN0YXRlIHtcbiAgc3dpdGNoIChlbmZvcmNlbWVudFN0YXRlU3RyKSB7XG4gICAgY2FzZSAnRU5GT1JDRSc6XG4gICAgICByZXR1cm4gRW5mb3JjZW1lbnRTdGF0ZS5FTkZPUkNFO1xuICAgIGNhc2UgJ0FVRElUJzpcbiAgICAgIHJldHVybiBFbmZvcmNlbWVudFN0YXRlLkFVRElUO1xuICAgIGNhc2UgJ09GRic6XG4gICAgICByZXR1cm4gRW5mb3JjZW1lbnRTdGF0ZS5PRkY7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBFbmZvcmNlbWVudFN0YXRlLkVORk9SQ0VNRU5UX1NUQVRFX1VOU1BFQ0lGSUVEO1xuICB9XG59XG5cbmNsYXNzIE5ldHdvcmtUaW1lb3V0PFQ+IHtcbiAgLy8gTm9kZSB0aW1lcnMgYW5kIGJyb3dzZXIgdGltZXJzIGFyZSBmdW5kYW1lbnRhbGx5IGluY29tcGF0aWJsZSwgYnV0IHdlXG4gIC8vIGRvbid0IGNhcmUgYWJvdXQgdGhlIHZhbHVlIGhlcmVcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgcHJpdmF0ZSB0aW1lcjogYW55IHwgbnVsbCA9IG51bGw7XG4gIHJlYWRvbmx5IHByb21pc2UgPSBuZXcgUHJvbWlzZTxUPigoXywgcmVqZWN0KSA9PiB7XG4gICAgdGhpcy50aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgX2NyZWF0ZUVycm9yKHRoaXMuYXV0aCwgQXV0aEVycm9yQ29kZS5ORVRXT1JLX1JFUVVFU1RfRkFJTEVEKVxuICAgICAgKTtcbiAgICB9LCBERUZBVUxUX0FQSV9USU1FT1VUX01TLmdldCgpKTtcbiAgfSk7XG5cbiAgY2xlYXJOZXR3b3JrVGltZW91dCgpOiB2b2lkIHtcbiAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGgpIHt9XG59XG5cbmludGVyZmFjZSBQb3RlbnRpYWxSZXNwb25zZSBleHRlbmRzIElkVG9rZW5SZXNwb25zZSB7XG4gIGVtYWlsPzogc3RyaW5nO1xuICBwaG9uZU51bWJlcj86IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9tYWtlVGFnZ2VkRXJyb3IoXG4gIGF1dGg6IEF1dGgsXG4gIGNvZGU6IEF1dGhFcnJvckNvZGUsXG4gIHJlc3BvbnNlOiBQb3RlbnRpYWxSZXNwb25zZVxuKTogRmlyZWJhc2VFcnJvciB7XG4gIGNvbnN0IGVycm9yUGFyYW1zOiBOYW1lZEVycm9yUGFyYW1zID0ge1xuICAgIGFwcE5hbWU6IGF1dGgubmFtZVxuICB9O1xuXG4gIGlmIChyZXNwb25zZS5lbWFpbCkge1xuICAgIGVycm9yUGFyYW1zLmVtYWlsID0gcmVzcG9uc2UuZW1haWw7XG4gIH1cbiAgaWYgKHJlc3BvbnNlLnBob25lTnVtYmVyKSB7XG4gICAgZXJyb3JQYXJhbXMucGhvbmVOdW1iZXIgPSByZXNwb25zZS5waG9uZU51bWJlcjtcbiAgfVxuXG4gIGNvbnN0IGVycm9yID0gX2NyZWF0ZUVycm9yKGF1dGgsIGNvZGUsIGVycm9yUGFyYW1zKTtcblxuICAvLyBXZSBrbm93IGN1c3RvbURhdGEgaXMgZGVmaW5lZCBvbiBlcnJvciBiZWNhdXNlIGVycm9yUGFyYW1zIGlzIGRlZmluZWRcbiAgKGVycm9yLmN1c3RvbURhdGEhIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlKS5fdG9rZW5SZXNwb25zZSA9IHJlc3BvbnNlO1xuICByZXR1cm4gZXJyb3I7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUmVjYXB0Y2hhUGFyYW1ldGVycyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQge1xuICBHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZSxcbiAgUmVjYXB0Y2hhRW5mb3JjZW1lbnRQcm92aWRlclN0YXRlXG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9yZWNhcHRjaGEnO1xuaW1wb3J0IHtcbiAgRW5mb3JjZW1lbnRTdGF0ZSxcbiAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyLFxuICBfcGFyc2VFbmZvcmNlbWVudFN0YXRlXG59IGZyb20gJy4uLy4uL2FwaS9pbmRleCc7XG5cbi8vIHJlQ0FQVENIQSB2MiBpbnRlcmZhY2VcbmV4cG9ydCBpbnRlcmZhY2UgUmVjYXB0Y2hhIHtcbiAgcmVuZGVyOiAoY29udGFpbmVyOiBIVE1MRWxlbWVudCwgcGFyYW1ldGVyczogUmVjYXB0Y2hhUGFyYW1ldGVycykgPT4gbnVtYmVyO1xuICBnZXRSZXNwb25zZTogKGlkOiBudW1iZXIpID0+IHN0cmluZztcbiAgZXhlY3V0ZTogKGlkOiBudW1iZXIpID0+IHVua25vd247XG4gIHJlc2V0OiAoaWQ6IG51bWJlcikgPT4gdW5rbm93bjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVjIoXG4gIGdyZWNhcHRjaGE6IFJlY2FwdGNoYSB8IEdyZUNBUFRDSEEgfCB1bmRlZmluZWRcbik6IGdyZWNhcHRjaGEgaXMgUmVjYXB0Y2hhIHtcbiAgcmV0dXJuIChcbiAgICBncmVjYXB0Y2hhICE9PSB1bmRlZmluZWQgJiZcbiAgICAoZ3JlY2FwdGNoYSBhcyBSZWNhcHRjaGEpLmdldFJlc3BvbnNlICE9PSB1bmRlZmluZWRcbiAgKTtcbn1cblxuLy8gcmVDQVBUQ0hBIEVudGVycHJpc2UgJiB2MyBzaGFyZWQgaW50ZXJmYWNlXG5leHBvcnQgaW50ZXJmYWNlIEdyZUNBUFRDSEFUb3BMZXZlbCBleHRlbmRzIEdyZUNBUFRDSEEge1xuICBlbnRlcnByaXNlOiBHcmVDQVBUQ0hBO1xufVxuXG4vLyByZUNBUFRDSEEgRW50ZXJwcmlzZSBpbnRlcmZhY2VcbmV4cG9ydCBpbnRlcmZhY2UgR3JlQ0FQVENIQSB7XG4gIHJlYWR5OiAoY2FsbGJhY2s6ICgpID0+IHZvaWQpID0+IHZvaWQ7XG4gIGV4ZWN1dGU6IChzaXRlS2V5OiBzdHJpbmcsIG9wdGlvbnM6IHsgYWN0aW9uOiBzdHJpbmcgfSkgPT4gUHJvbWlzZTxzdHJpbmc+O1xuICByZW5kZXI6IChcbiAgICBjb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIHBhcmFtZXRlcnM6IEdyZUNBUFRDSEFSZW5kZXJPcHRpb25cbiAgKSA9PiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3JlQ0FQVENIQVJlbmRlck9wdGlvbiB7XG4gIHNpdGVrZXk6IHN0cmluZztcbiAgc2l6ZTogJ2ludmlzaWJsZSc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0VudGVycHJpc2UoXG4gIGdyZWNhcHRjaGE6IFJlY2FwdGNoYSB8IEdyZUNBUFRDSEEgfCB1bmRlZmluZWRcbik6IGdyZWNhcHRjaGEgaXMgR3JlQ0FQVENIQVRvcExldmVsIHtcbiAgcmV0dXJuIChcbiAgICBncmVjYXB0Y2hhICE9PSB1bmRlZmluZWQgJiZcbiAgICAoZ3JlY2FwdGNoYSBhcyBHcmVDQVBUQ0hBVG9wTGV2ZWwpLmVudGVycHJpc2UgIT09IHVuZGVmaW5lZFxuICApO1xufVxuXG4vLyBUT0RPKGNodWFucik6IFJlcGxhY2UgdGhpcyB3aXRoIHRoZSBBdXRoV2luZG93IGFmdGVyIHJlc29sdmluZyB0aGUgZGVwZW5kZW5jeSBpc3N1ZSBpbiBOb2RlLmpzIGVudi5cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgaW50ZXJmYWNlIFdpbmRvdyB7XG4gICAgZ3JlY2FwdGNoYT86IFJlY2FwdGNoYSB8IEdyZUNBUFRDSEFUb3BMZXZlbDtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUmVjYXB0Y2hhQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSByZUNBUFRDSEEgc2l0ZSBrZXkuXG4gICAqL1xuICBzaXRlS2V5OiBzdHJpbmcgPSAnJztcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgcHJvdmlkZXJzIGFuZCB0aGVpciBlbmFibGVtZW50IHN0YXR1cyBmb3IgcmVDQVBUQ0hBIEVudGVycHJpc2UuXG4gICAqL1xuICByZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlOiBSZWNhcHRjaGFFbmZvcmNlbWVudFByb3ZpZGVyU3RhdGVbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKHJlc3BvbnNlOiBHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZSkge1xuICAgIGlmIChyZXNwb25zZS5yZWNhcHRjaGFLZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWNhcHRjaGFLZXkgdW5kZWZpbmVkJyk7XG4gICAgfVxuICAgIC8vIEV4YW1wbGUgcmVzcG9uc2UucmVjYXB0Y2hhS2V5OiBcInByb2plY3RzL3Byb2oxMjMva2V5cy9zaXRla2V5MTIzXCJcbiAgICB0aGlzLnNpdGVLZXkgPSByZXNwb25zZS5yZWNhcHRjaGFLZXkuc3BsaXQoJy8nKVszXTtcbiAgICB0aGlzLnJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUgPSByZXNwb25zZS5yZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHJlQ0FQVENIQSBFbnRlcnByaXNlIGVuZm9yY2VtZW50IHN0YXRlIGZvciB0aGUgZ2l2ZW4gcHJvdmlkZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwcm92aWRlclN0ciAtIFRoZSBwcm92aWRlciB3aG9zZSBlbmZvcmNlbWVudCBzdGF0ZSBpcyB0byBiZSByZXR1cm5lZC5cbiAgICogQHJldHVybnMgVGhlIHJlQ0FQVENIQSBFbnRlcnByaXNlIGVuZm9yY2VtZW50IHN0YXRlIGZvciB0aGUgZ2l2ZW4gcHJvdmlkZXIuXG4gICAqL1xuICBnZXRQcm92aWRlckVuZm9yY2VtZW50U3RhdGUocHJvdmlkZXJTdHI6IHN0cmluZyk6IEVuZm9yY2VtZW50U3RhdGUgfCBudWxsIHtcbiAgICBpZiAoXG4gICAgICAhdGhpcy5yZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlIHx8XG4gICAgICB0aGlzLnJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUubGVuZ3RoID09PSAwXG4gICAgKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUgb2YgdGhpcy5yZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUucHJvdmlkZXIgJiZcbiAgICAgICAgcmVjYXB0Y2hhRW5mb3JjZW1lbnRTdGF0ZS5wcm92aWRlciA9PT0gcHJvdmlkZXJTdHJcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gX3BhcnNlRW5mb3JjZW1lbnRTdGF0ZShcbiAgICAgICAgICByZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlLmVuZm9yY2VtZW50U3RhdGVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoZSByZUNBUFRDSEEgRW50ZXJwcmlzZSBlbmZvcmNlbWVudCBzdGF0ZSBmb3IgdGhlIHByb3ZpZGVyIGlzIHNldCB0byBFTkZPUkNFIG9yIEFVRElULlxuICAgKlxuICAgKiBAcGFyYW0gcHJvdmlkZXJTdHIgLSBUaGUgcHJvdmlkZXIgd2hvc2UgZW5hYmxlbWVudCBzdGF0ZSBpcyB0byBiZSByZXR1cm5lZC5cbiAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgcmVDQVBUQ0hBIEVudGVycHJpc2UgcHJvdGVjdGlvbiBpcyBlbmFibGVkIGZvciB0aGUgZ2l2ZW4gcHJvdmlkZXIuXG4gICAqL1xuICBpc1Byb3ZpZGVyRW5hYmxlZChwcm92aWRlclN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuZ2V0UHJvdmlkZXJFbmZvcmNlbWVudFN0YXRlKHByb3ZpZGVyU3RyKSA9PT1cbiAgICAgICAgRW5mb3JjZW1lbnRTdGF0ZS5FTkZPUkNFIHx8XG4gICAgICB0aGlzLmdldFByb3ZpZGVyRW5mb3JjZW1lbnRTdGF0ZShwcm92aWRlclN0cikgPT09IEVuZm9yY2VtZW50U3RhdGUuQVVESVRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiByZUNBUFRDSEEgRW50ZXJwcmlzZSBwcm90ZWN0aW9uIGlzIGVuYWJsZWQgaW4gYXQgbGVhc3Qgb25lIHByb3ZpZGVyLCBvdGhlcndpc2VcbiAgICogcmV0dXJucyBmYWxzZS5cbiAgICpcbiAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgcmVDQVBUQ0hBIEVudGVycHJpc2UgcHJvdGVjdGlvbiBpcyBlbmFibGVkIGZvciBhdCBsZWFzdCBvbmUgcHJvdmlkZXIuXG4gICAqL1xuICBpc0FueVByb3ZpZGVyRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5pc1Byb3ZpZGVyRW5hYmxlZChSZWNhcHRjaGFBdXRoUHJvdmlkZXIuRU1BSUxfUEFTU1dPUkRfUFJPVklERVIpIHx8XG4gICAgICB0aGlzLmlzUHJvdmlkZXJFbmFibGVkKFJlY2FwdGNoYUF1dGhQcm92aWRlci5QSE9ORV9QUk9WSURFUilcbiAgICApO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYVZlcnNpb24sXG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgX2FkZFRpZElmTmVjZXNzYXJ5XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEF1dGggfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbnRlcmZhY2UgR2V0UmVjYXB0Y2hhUGFyYW1SZXNwb25zZSB7XG4gIHJlY2FwdGNoYVNpdGVLZXk/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSZWNhcHRjaGFQYXJhbXMoYXV0aDogQXV0aCk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiAoXG4gICAgKFxuICAgICAgYXdhaXQgX3BlcmZvcm1BcGlSZXF1ZXN0PHZvaWQsIEdldFJlY2FwdGNoYVBhcmFtUmVzcG9uc2U+KFxuICAgICAgICBhdXRoLFxuICAgICAgICBIdHRwTWV0aG9kLkdFVCxcbiAgICAgICAgRW5kcG9pbnQuR0VUX1JFQ0FQVENIQV9QQVJBTVxuICAgICAgKVxuICAgICkucmVjYXB0Y2hhU2l0ZUtleSB8fCAnJ1xuICApO1xufVxuXG4vLyBUaGUgZm9sbG93aW5nIGZ1bmN0aW9ucyBhcmUgZm9yIHJlQ0FQVENIQSBlbnRlcnByaXNlIGludGVncmF0aW9uLlxuaW50ZXJmYWNlIEdldFJlY2FwdGNoYUNvbmZpZ1JlcXVlc3Qge1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY2FwdGNoYUVuZm9yY2VtZW50UHJvdmlkZXJTdGF0ZSB7XG4gIHByb3ZpZGVyOiBzdHJpbmc7XG4gIGVuZm9yY2VtZW50U3RhdGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZSB7XG4gIHJlY2FwdGNoYUtleTogc3RyaW5nO1xuICByZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlOiBSZWNhcHRjaGFFbmZvcmNlbWVudFByb3ZpZGVyU3RhdGVbXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFJlY2FwdGNoYUNvbmZpZyhcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogR2V0UmVjYXB0Y2hhQ29uZmlnUmVxdWVzdFxuKTogUHJvbWlzZTxHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIEdldFJlY2FwdGNoYUNvbmZpZ1JlcXVlc3QsXG4gICAgR2V0UmVjYXB0Y2hhQ29uZmlnUmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuR0VULFxuICAgIEVuZHBvaW50LkdFVF9SRUNBUFRDSEFfQ09ORklHLFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEVuZHBvaW50LCBIdHRwTWV0aG9kLCBfcGVyZm9ybUFwaVJlcXVlc3QgfSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBNZmFFbnJvbGxtZW50IH0gZnJvbSAnLi9tZmEnO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlQWNjb3VudFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVBY2NvdW50KFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBEZWxldGVBY2NvdW50UmVxdWVzdFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8RGVsZXRlQWNjb3VudFJlcXVlc3QsIHZvaWQ+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LkRFTEVURV9BQ0NPVU5ULFxuICAgIHJlcXVlc3RcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlclVzZXJJbmZvIHtcbiAgcHJvdmlkZXJJZDogc3RyaW5nO1xuICByYXdJZD86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xuICBwaG90b1VybD86IHN0cmluZztcbiAgcGhvbmVOdW1iZXI/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlTGlua2VkQWNjb3VudHNSZXF1ZXN0IHtcbiAgaWRUb2tlbjogc3RyaW5nO1xuICBkZWxldGVQcm92aWRlcjogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlTGlua2VkQWNjb3VudHNSZXNwb25zZSB7XG4gIHByb3ZpZGVyVXNlckluZm86IFByb3ZpZGVyVXNlckluZm9bXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZUxpbmtlZEFjY291bnRzKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBEZWxldGVMaW5rZWRBY2NvdW50c1JlcXVlc3Rcbik6IFByb21pc2U8RGVsZXRlTGlua2VkQWNjb3VudHNSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIERlbGV0ZUxpbmtlZEFjY291bnRzUmVxdWVzdCxcbiAgICBEZWxldGVMaW5rZWRBY2NvdW50c1Jlc3BvbnNlXG4gID4oYXV0aCwgSHR0cE1ldGhvZC5QT1NULCBFbmRwb2ludC5TRVRfQUNDT1VOVF9JTkZPLCByZXF1ZXN0KTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBUElVc2VySW5mbyB7XG4gIGxvY2FsSWQ/OiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xuICBwaG90b1VybD86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG4gIGVtYWlsVmVyaWZpZWQ/OiBib29sZWFuO1xuICBwaG9uZU51bWJlcj86IHN0cmluZztcbiAgbGFzdExvZ2luQXQ/OiBudW1iZXI7XG4gIGNyZWF0ZWRBdD86IG51bWJlcjtcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG4gIHBhc3N3b3JkSGFzaD86IHN0cmluZztcbiAgcHJvdmlkZXJVc2VySW5mbz86IFByb3ZpZGVyVXNlckluZm9bXTtcbiAgbWZhSW5mbz86IE1mYUVucm9sbG1lbnRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRBY2NvdW50SW5mb1JlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0QWNjb3VudEluZm9SZXNwb25zZSB7XG4gIHVzZXJzOiBBUElVc2VySW5mb1tdO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWNjb3VudEluZm8oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IEdldEFjY291bnRJbmZvUmVxdWVzdFxuKTogUHJvbWlzZTxHZXRBY2NvdW50SW5mb1Jlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8R2V0QWNjb3VudEluZm9SZXF1ZXN0LCBHZXRBY2NvdW50SW5mb1Jlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5HRVRfQUNDT1VOVF9JTkZPLFxuICAgIHJlcXVlc3RcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdXRjVGltZXN0YW1wVG9EYXRlU3RyaW5nKFxuICB1dGNUaW1lc3RhbXA/OiBzdHJpbmcgfCBudW1iZXJcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghdXRjVGltZXN0YW1wKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICB0cnkge1xuICAgIC8vIENvbnZlcnQgdG8gZGF0ZSBvYmplY3QuXG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKE51bWJlcih1dGNUaW1lc3RhbXApKTtcbiAgICAvLyBUZXN0IGRhdGUgaXMgdmFsaWQuXG4gICAgaWYgKCFpc05hTihkYXRlLmdldFRpbWUoKSkpIHtcbiAgICAgIC8vIENvbnZlcnQgdG8gVVRDIGRhdGUgc3RyaW5nLlxuICAgICAgcmV0dXJuIGRhdGUudG9VVENTdHJpbmcoKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBEbyBub3RoaW5nLiB1bmRlZmluZWQgd2lsbCBiZSByZXR1cm5lZC5cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IElkVG9rZW5SZXN1bHQsIFBhcnNlZFRva2VuLCBVc2VyIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IGJhc2U2NERlY29kZSwgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfbG9nRXJyb3IgfSBmcm9tICcuLi91dGlsL2xvZyc7XG5pbXBvcnQgeyB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcgfSBmcm9tICcuLi91dGlsL3RpbWUnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbi8qKlxuICogUmV0dXJucyBhIEpTT04gV2ViIFRva2VuIChKV1QpIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHVzZXIgdG8gYSBGaXJlYmFzZSBzZXJ2aWNlLlxuICpcbiAqIEByZW1hcmtzXG4gKiBSZXR1cm5zIHRoZSBjdXJyZW50IHRva2VuIGlmIGl0IGhhcyBub3QgZXhwaXJlZCBvciBpZiBpdCB3aWxsIG5vdCBleHBpcmUgaW4gdGhlIG5leHQgZml2ZVxuICogbWludXRlcy4gT3RoZXJ3aXNlLCB0aGlzIHdpbGwgcmVmcmVzaCB0aGUgdG9rZW4gYW5kIHJldHVybiBhIG5ldyBvbmUuXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBmb3JjZVJlZnJlc2ggLSBGb3JjZSByZWZyZXNoIHJlZ2FyZGxlc3Mgb2YgdG9rZW4gZXhwaXJhdGlvbi5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJZFRva2VuKHVzZXI6IFVzZXIsIGZvcmNlUmVmcmVzaCA9IGZhbHNlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKS5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGRlc2VyaWFsaXplZCBKU09OIFdlYiBUb2tlbiAoSldUKSB1c2VkIHRvIGlkZW50aWZ5IHRoZSB1c2VyIHRvIGEgRmlyZWJhc2Ugc2VydmljZS5cbiAqXG4gKiBAcmVtYXJrc1xuICogUmV0dXJucyB0aGUgY3VycmVudCB0b2tlbiBpZiBpdCBoYXMgbm90IGV4cGlyZWQgb3IgaWYgaXQgd2lsbCBub3QgZXhwaXJlIGluIHRoZSBuZXh0IGZpdmVcbiAqIG1pbnV0ZXMuIE90aGVyd2lzZSwgdGhpcyB3aWxsIHJlZnJlc2ggdGhlIHRva2VuIGFuZCByZXR1cm4gYSBuZXcgb25lLlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gZm9yY2VSZWZyZXNoIC0gRm9yY2UgcmVmcmVzaCByZWdhcmRsZXNzIG9mIHRva2VuIGV4cGlyYXRpb24uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0SWRUb2tlblJlc3VsdChcbiAgdXNlcjogVXNlcixcbiAgZm9yY2VSZWZyZXNoID0gZmFsc2Vcbik6IFByb21pc2U8SWRUb2tlblJlc3VsdD4ge1xuICBjb25zdCB1c2VySW50ZXJuYWwgPSBnZXRNb2R1bGFySW5zdGFuY2UodXNlcikgYXMgVXNlckludGVybmFsO1xuICBjb25zdCB0b2tlbiA9IGF3YWl0IHVzZXJJbnRlcm5hbC5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG4gIGNvbnN0IGNsYWltcyA9IF9wYXJzZVRva2VuKHRva2VuKTtcblxuICBfYXNzZXJ0KFxuICAgIGNsYWltcyAmJiBjbGFpbXMuZXhwICYmIGNsYWltcy5hdXRoX3RpbWUgJiYgY2xhaW1zLmlhdCxcbiAgICB1c2VySW50ZXJuYWwuYXV0aCxcbiAgICBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SXG4gICk7XG4gIGNvbnN0IGZpcmViYXNlID1cbiAgICB0eXBlb2YgY2xhaW1zLmZpcmViYXNlID09PSAnb2JqZWN0JyA/IGNsYWltcy5maXJlYmFzZSA6IHVuZGVmaW5lZDtcblxuICBjb25zdCBzaWduSW5Qcm92aWRlcjogc3RyaW5nIHwgdW5kZWZpbmVkID0gZmlyZWJhc2U/Llsnc2lnbl9pbl9wcm92aWRlciddO1xuXG4gIHJldHVybiB7XG4gICAgY2xhaW1zLFxuICAgIHRva2VuLFxuICAgIGF1dGhUaW1lOiB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcoXG4gICAgICBzZWNvbmRzU3RyaW5nVG9NaWxsaXNlY29uZHMoY2xhaW1zLmF1dGhfdGltZSlcbiAgICApISxcbiAgICBpc3N1ZWRBdFRpbWU6IHV0Y1RpbWVzdGFtcFRvRGF0ZVN0cmluZyhcbiAgICAgIHNlY29uZHNTdHJpbmdUb01pbGxpc2Vjb25kcyhjbGFpbXMuaWF0KVxuICAgICkhLFxuICAgIGV4cGlyYXRpb25UaW1lOiB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcoXG4gICAgICBzZWNvbmRzU3RyaW5nVG9NaWxsaXNlY29uZHMoY2xhaW1zLmV4cClcbiAgICApISxcbiAgICBzaWduSW5Qcm92aWRlcjogc2lnbkluUHJvdmlkZXIgfHwgbnVsbCxcbiAgICBzaWduSW5TZWNvbmRGYWN0b3I6IGZpcmViYXNlPy5bJ3NpZ25faW5fc2Vjb25kX2ZhY3RvciddIHx8IG51bGxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2Vjb25kc1N0cmluZ1RvTWlsbGlzZWNvbmRzKHNlY29uZHM6IHN0cmluZyk6IG51bWJlciB7XG4gIHJldHVybiBOdW1iZXIoc2Vjb25kcykgKiAxMDAwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3BhcnNlVG9rZW4odG9rZW46IHN0cmluZyk6IFBhcnNlZFRva2VuIHwgbnVsbCB7XG4gIGNvbnN0IFthbGdvcml0aG0sIHBheWxvYWQsIHNpZ25hdHVyZV0gPSB0b2tlbi5zcGxpdCgnLicpO1xuICBpZiAoXG4gICAgYWxnb3JpdGhtID09PSB1bmRlZmluZWQgfHxcbiAgICBwYXlsb2FkID09PSB1bmRlZmluZWQgfHxcbiAgICBzaWduYXR1cmUgPT09IHVuZGVmaW5lZFxuICApIHtcbiAgICBfbG9nRXJyb3IoJ0pXVCBtYWxmb3JtZWQsIGNvbnRhaW5lZCBmZXdlciB0aGFuIDMgc2VjdGlvbnMnKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgZGVjb2RlZCA9IGJhc2U2NERlY29kZShwYXlsb2FkKTtcbiAgICBpZiAoIWRlY29kZWQpIHtcbiAgICAgIF9sb2dFcnJvcignRmFpbGVkIHRvIGRlY29kZSBiYXNlNjQgSldUIHBheWxvYWQnKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gSlNPTi5wYXJzZShkZWNvZGVkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIF9sb2dFcnJvcihcbiAgICAgICdDYXVnaHQgZXJyb3IgcGFyc2luZyBKV1QgcGF5bG9hZCBhcyBKU09OJyxcbiAgICAgIChlIGFzIEVycm9yKT8udG9TdHJpbmcoKVxuICAgICk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBFeHRyYWN0IGV4cGlyZXNJbiBUVEwgZnJvbSBhIHRva2VuIGJ5IHN1YnRyYWN0aW5nIHRoZSBleHBpcmF0aW9uIGZyb20gdGhlIGlzc3VhbmNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gX3Rva2VuRXhwaXJlc0luKHRva2VuOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCBwYXJzZWRUb2tlbiA9IF9wYXJzZVRva2VuKHRva2VuKTtcbiAgX2Fzc2VydChwYXJzZWRUb2tlbiwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gIF9hc3NlcnQodHlwZW9mIHBhcnNlZFRva2VuLmV4cCAhPT0gJ3VuZGVmaW5lZCcsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICBfYXNzZXJ0KHR5cGVvZiBwYXJzZWRUb2tlbi5pYXQgIT09ICd1bmRlZmluZWQnLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgcmV0dXJuIE51bWJlcihwYXJzZWRUb2tlbi5leHApIC0gTnVtYmVyKHBhcnNlZFRva2VuLmlhdCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9sb2dvdXRJZkludmFsaWRhdGVkPFQ+KFxuICB1c2VyOiBVc2VySW50ZXJuYWwsXG4gIHByb21pc2U6IFByb21pc2U8VD4sXG4gIGJ5cGFzc0F1dGhTdGF0ZSA9IGZhbHNlXG4pOiBQcm9taXNlPFQ+IHtcbiAgaWYgKGJ5cGFzc0F1dGhTdGF0ZSkge1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHByb21pc2U7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIEZpcmViYXNlRXJyb3IgJiYgaXNVc2VySW52YWxpZGF0ZWQoZSkpIHtcbiAgICAgIGlmICh1c2VyLmF1dGguY3VycmVudFVzZXIgPT09IHVzZXIpIHtcbiAgICAgICAgYXdhaXQgdXNlci5hdXRoLnNpZ25PdXQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzVXNlckludmFsaWRhdGVkKHsgY29kZSB9OiBGaXJlYmFzZUVycm9yKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgY29kZSA9PT0gYGF1dGgvJHtBdXRoRXJyb3JDb2RlLlVTRVJfRElTQUJMRUR9YCB8fFxuICAgIGNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5UT0tFTl9FWFBJUkVEfWBcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuLy8gUmVmcmVzaCB0aGUgdG9rZW4gZml2ZSBtaW51dGVzIGJlZm9yZSBleHBpcmF0aW9uXG5leHBvcnQgY29uc3QgZW51bSBEdXJhdGlvbiB7XG4gIE9GRlNFVCA9IDUgKiAxMDAwICogNjAsXG4gIFJFVFJZX0JBQ0tPRkZfTUlOID0gMzAgKiAxMDAwLFxuICBSRVRSWV9CQUNLT0ZGX01BWCA9IDE2ICogNjAgKiAxMDAwXG59XG5cbmV4cG9ydCBjbGFzcyBQcm9hY3RpdmVSZWZyZXNoIHtcbiAgcHJpdmF0ZSBpc1J1bm5pbmcgPSBmYWxzZTtcblxuICAvLyBOb2RlIHRpbWVycyBhbmQgYnJvd3NlciB0aW1lcnMgcmV0dXJuIGZ1bmRhbWVudGFsbHkgZGlmZmVyZW50IHR5cGVzLlxuICAvLyBXZSBkb24ndCBhY3R1YWxseSBjYXJlIHdoYXQgdGhlIHZhbHVlIGlzIGJ1dCBUUyB3b24ndCBhY2NlcHQgdW5rbm93biBhbmRcbiAgLy8gd2UgY2FuJ3QgY2FzdCBwcm9wZXJseSBpbiBib3RoIGVudmlyb25tZW50cy5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgcHJpdmF0ZSB0aW1lcklkOiBhbnkgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBlcnJvckJhY2tvZmYgPSBEdXJhdGlvbi5SRVRSWV9CQUNLT0ZGX01JTjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHVzZXI6IFVzZXJJbnRlcm5hbCkge31cblxuICBfc3RhcnQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNSdW5uaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5pc1J1bm5pbmcgPSB0cnVlO1xuICAgIHRoaXMuc2NoZWR1bGUoKTtcbiAgfVxuXG4gIF9zdG9wKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc1J1bm5pbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlzUnVubmluZyA9IGZhbHNlO1xuICAgIGlmICh0aGlzLnRpbWVySWQgIT09IG51bGwpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVySWQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0SW50ZXJ2YWwod2FzRXJyb3I6IGJvb2xlYW4pOiBudW1iZXIge1xuICAgIGlmICh3YXNFcnJvcikge1xuICAgICAgY29uc3QgaW50ZXJ2YWwgPSB0aGlzLmVycm9yQmFja29mZjtcbiAgICAgIHRoaXMuZXJyb3JCYWNrb2ZmID0gTWF0aC5taW4oXG4gICAgICAgIHRoaXMuZXJyb3JCYWNrb2ZmICogMixcbiAgICAgICAgRHVyYXRpb24uUkVUUllfQkFDS09GRl9NQVhcbiAgICAgICk7XG4gICAgICByZXR1cm4gaW50ZXJ2YWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlc2V0IHRoZSBlcnJvciBiYWNrb2ZmXG4gICAgICB0aGlzLmVycm9yQmFja29mZiA9IER1cmF0aW9uLlJFVFJZX0JBQ0tPRkZfTUlOO1xuICAgICAgY29uc3QgZXhwVGltZSA9IHRoaXMudXNlci5zdHNUb2tlbk1hbmFnZXIuZXhwaXJhdGlvblRpbWUgPz8gMDtcbiAgICAgIGNvbnN0IGludGVydmFsID0gZXhwVGltZSAtIERhdGUubm93KCkgLSBEdXJhdGlvbi5PRkZTRVQ7XG5cbiAgICAgIHJldHVybiBNYXRoLm1heCgwLCBpbnRlcnZhbCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzY2hlZHVsZSh3YXNFcnJvciA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzUnVubmluZykge1xuICAgICAgLy8gSnVzdCBpbiBjYXNlLi4uXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaW50ZXJ2YWwgPSB0aGlzLmdldEludGVydmFsKHdhc0Vycm9yKTtcbiAgICB0aGlzLnRpbWVySWQgPSBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMuaXRlcmF0aW9uKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpdGVyYXRpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudXNlci5nZXRJZFRva2VuKHRydWUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIE9ubHkgcmV0cnkgb24gbmV0d29yayBlcnJvcnNcbiAgICAgIGlmIChcbiAgICAgICAgKGUgYXMgRmlyZWJhc2VFcnJvcik/LmNvZGUgPT09XG4gICAgICAgIGBhdXRoLyR7QXV0aEVycm9yQ29kZS5ORVRXT1JLX1JFUVVFU1RfRkFJTEVEfWBcbiAgICAgICkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlKC8qIHdhc0Vycm9yICovIHRydWUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc2NoZWR1bGUoKTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXJNZXRhZGF0YSBhcyBVc2VyTWV0YWRhdGFUeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgdXRjVGltZXN0YW1wVG9EYXRlU3RyaW5nIH0gZnJvbSAnLi4vdXRpbC90aW1lJztcblxuZXhwb3J0IGNsYXNzIFVzZXJNZXRhZGF0YSBpbXBsZW1lbnRzIFVzZXJNZXRhZGF0YVR5cGUge1xuICBjcmVhdGlvblRpbWU/OiBzdHJpbmc7XG4gIGxhc3RTaWduSW5UaW1lPzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY3JlYXRlZEF0Pzogc3RyaW5nIHwgbnVtYmVyLFxuICAgIHByaXZhdGUgbGFzdExvZ2luQXQ/OiBzdHJpbmcgfCBudW1iZXJcbiAgKSB7XG4gICAgdGhpcy5faW5pdGlhbGl6ZVRpbWUoKTtcbiAgfVxuXG4gIHByaXZhdGUgX2luaXRpYWxpemVUaW1lKCk6IHZvaWQge1xuICAgIHRoaXMubGFzdFNpZ25JblRpbWUgPSB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcodGhpcy5sYXN0TG9naW5BdCk7XG4gICAgdGhpcy5jcmVhdGlvblRpbWUgPSB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcodGhpcy5jcmVhdGVkQXQpO1xuICB9XG5cbiAgX2NvcHkobWV0YWRhdGE6IFVzZXJNZXRhZGF0YSk6IHZvaWQge1xuICAgIHRoaXMuY3JlYXRlZEF0ID0gbWV0YWRhdGEuY3JlYXRlZEF0O1xuICAgIHRoaXMubGFzdExvZ2luQXQgPSBtZXRhZGF0YS5sYXN0TG9naW5BdDtcbiAgICB0aGlzLl9pbml0aWFsaXplVGltZSgpO1xuICB9XG5cbiAgdG9KU09OKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNyZWF0ZWRBdDogdGhpcy5jcmVhdGVkQXQsXG4gICAgICBsYXN0TG9naW5BdDogdGhpcy5sYXN0TG9naW5BdFxuICAgIH07XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVc2VyLCBVc2VySW5mbyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7XG4gIGdldEFjY291bnRJbmZvLFxuICBQcm92aWRlclVzZXJJbmZvXG59IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvYWNjb3VudCc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCB9IGZyb20gJy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgVXNlck1ldGFkYXRhIH0gZnJvbSAnLi91c2VyX21ldGFkYXRhJztcbmltcG9ydCB7IGdldE1vZHVsYXJJbnN0YW5jZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9yZWxvYWRXaXRob3V0U2F2aW5nKHVzZXI6IFVzZXJJbnRlcm5hbCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhdXRoID0gdXNlci5hdXRoO1xuICBjb25zdCBpZFRva2VuID0gYXdhaXQgdXNlci5nZXRJZFRva2VuKCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQoXG4gICAgdXNlcixcbiAgICBnZXRBY2NvdW50SW5mbyhhdXRoLCB7IGlkVG9rZW4gfSlcbiAgKTtcblxuICBfYXNzZXJ0KHJlc3BvbnNlPy51c2Vycy5sZW5ndGgsIGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuXG4gIGNvbnN0IGNvcmVBY2NvdW50ID0gcmVzcG9uc2UudXNlcnNbMF07XG5cbiAgdXNlci5fbm90aWZ5UmVsb2FkTGlzdGVuZXIoY29yZUFjY291bnQpO1xuXG4gIGNvbnN0IG5ld1Byb3ZpZGVyRGF0YSA9IGNvcmVBY2NvdW50LnByb3ZpZGVyVXNlckluZm8/Lmxlbmd0aFxuICAgID8gZXh0cmFjdFByb3ZpZGVyRGF0YShjb3JlQWNjb3VudC5wcm92aWRlclVzZXJJbmZvKVxuICAgIDogW107XG5cbiAgY29uc3QgcHJvdmlkZXJEYXRhID0gbWVyZ2VQcm92aWRlckRhdGEodXNlci5wcm92aWRlckRhdGEsIG5ld1Byb3ZpZGVyRGF0YSk7XG5cbiAgLy8gUHJlc2VydmVzIHRoZSBub24tbm9ueW1vdXMgc3RhdHVzIG9mIHRoZSBzdG9yZWQgdXNlciwgZXZlbiBpZiBubyBtb3JlXG4gIC8vIGNyZWRlbnRpYWxzIChmZWRlcmF0ZWQgb3IgZW1haWwvcGFzc3dvcmQpIGFyZSBsaW5rZWQgdG8gdGhlIHVzZXIuIElmXG4gIC8vIHRoZSB1c2VyIHdhcyBwcmV2aW91c2x5IGFub255bW91cywgdGhlbiB1c2UgcHJvdmlkZXIgZGF0YSB0byB1cGRhdGUuXG4gIC8vIE9uIHRoZSBvdGhlciBoYW5kLCBpZiBpdCB3YXMgbm90IGFub255bW91cyBiZWZvcmUsIGl0IHNob3VsZCBuZXZlciBiZVxuICAvLyBjb25zaWRlcmVkIGFub255bW91cyBub3cuXG4gIGNvbnN0IG9sZElzQW5vbnltb3VzID0gdXNlci5pc0Fub255bW91cztcbiAgY29uc3QgbmV3SXNBbm9ueW1vdXMgPVxuICAgICEodXNlci5lbWFpbCAmJiBjb3JlQWNjb3VudC5wYXNzd29yZEhhc2gpICYmICFwcm92aWRlckRhdGE/Lmxlbmd0aDtcbiAgY29uc3QgaXNBbm9ueW1vdXMgPSAhb2xkSXNBbm9ueW1vdXMgPyBmYWxzZSA6IG5ld0lzQW5vbnltb3VzO1xuXG4gIGNvbnN0IHVwZGF0ZXM6IFBhcnRpYWw8VXNlckludGVybmFsPiA9IHtcbiAgICB1aWQ6IGNvcmVBY2NvdW50LmxvY2FsSWQsXG4gICAgZGlzcGxheU5hbWU6IGNvcmVBY2NvdW50LmRpc3BsYXlOYW1lIHx8IG51bGwsXG4gICAgcGhvdG9VUkw6IGNvcmVBY2NvdW50LnBob3RvVXJsIHx8IG51bGwsXG4gICAgZW1haWw6IGNvcmVBY2NvdW50LmVtYWlsIHx8IG51bGwsXG4gICAgZW1haWxWZXJpZmllZDogY29yZUFjY291bnQuZW1haWxWZXJpZmllZCB8fCBmYWxzZSxcbiAgICBwaG9uZU51bWJlcjogY29yZUFjY291bnQucGhvbmVOdW1iZXIgfHwgbnVsbCxcbiAgICB0ZW5hbnRJZDogY29yZUFjY291bnQudGVuYW50SWQgfHwgbnVsbCxcbiAgICBwcm92aWRlckRhdGEsXG4gICAgbWV0YWRhdGE6IG5ldyBVc2VyTWV0YWRhdGEoY29yZUFjY291bnQuY3JlYXRlZEF0LCBjb3JlQWNjb3VudC5sYXN0TG9naW5BdCksXG4gICAgaXNBbm9ueW1vdXNcbiAgfTtcblxuICBPYmplY3QuYXNzaWduKHVzZXIsIHVwZGF0ZXMpO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdXNlciBhY2NvdW50IGRhdGEsIGlmIHNpZ25lZCBpbi5cbiAqXG4gKiBAcGFyYW0gdXNlciAtIFRoZSB1c2VyLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbG9hZCh1c2VyOiBVc2VyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbDogVXNlckludGVybmFsID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbDtcbiAgYXdhaXQgX3JlbG9hZFdpdGhvdXRTYXZpbmcodXNlckludGVybmFsKTtcblxuICAvLyBFdmVuIHRob3VnaCB0aGUgY3VycmVudCB1c2VyIGhhc24ndCBjaGFuZ2VkLCB1cGRhdGVcbiAgLy8gY3VycmVudCB1c2VyIHdpbGwgdHJpZ2dlciBhIHBlcnNpc3RlbmNlIHVwZGF0ZSB3LyB0aGVcbiAgLy8gbmV3IGluZm8uXG4gIGF3YWl0IHVzZXJJbnRlcm5hbC5hdXRoLl9wZXJzaXN0VXNlcklmQ3VycmVudCh1c2VySW50ZXJuYWwpO1xuICB1c2VySW50ZXJuYWwuYXV0aC5fbm90aWZ5TGlzdGVuZXJzSWZDdXJyZW50KHVzZXJJbnRlcm5hbCk7XG59XG5cbmZ1bmN0aW9uIG1lcmdlUHJvdmlkZXJEYXRhKFxuICBvcmlnaW5hbDogVXNlckluZm9bXSxcbiAgbmV3RGF0YTogVXNlckluZm9bXVxuKTogVXNlckluZm9bXSB7XG4gIGNvbnN0IGRlZHVwZWQgPSBvcmlnaW5hbC5maWx0ZXIoXG4gICAgbyA9PiAhbmV3RGF0YS5zb21lKG4gPT4gbi5wcm92aWRlcklkID09PSBvLnByb3ZpZGVySWQpXG4gICk7XG4gIHJldHVybiBbLi4uZGVkdXBlZCwgLi4ubmV3RGF0YV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0UHJvdmlkZXJEYXRhKHByb3ZpZGVyczogUHJvdmlkZXJVc2VySW5mb1tdKTogVXNlckluZm9bXSB7XG4gIHJldHVybiBwcm92aWRlcnMubWFwKCh7IHByb3ZpZGVySWQsIC4uLnByb3ZpZGVyIH0pID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvdmlkZXJJZCxcbiAgICAgIHVpZDogcHJvdmlkZXIucmF3SWQgfHwgJycsXG4gICAgICBkaXNwbGF5TmFtZTogcHJvdmlkZXIuZGlzcGxheU5hbWUgfHwgbnVsbCxcbiAgICAgIGVtYWlsOiBwcm92aWRlci5lbWFpbCB8fCBudWxsLFxuICAgICAgcGhvbmVOdW1iZXI6IHByb3ZpZGVyLnBob25lTnVtYmVyIHx8IG51bGwsXG4gICAgICBwaG90b1VSTDogcHJvdmlkZXIucGhvdG9VcmwgfHwgbnVsbFxuICAgIH07XG4gIH0pO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qIGVzbGludC1kaXNhYmxlIGNhbWVsY2FzZSAqL1xuXG5pbXBvcnQgeyBpc0Nsb3VkV29ya3N0YXRpb24sIHF1ZXJ5c3RyaW5nIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQge1xuICBfZ2V0RmluYWxUYXJnZXQsXG4gIF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZyxcbiAgX3BlcmZvcm1BcGlSZXF1ZXN0LFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIEh0dHBNZXRob2QsXG4gIEh0dHBIZWFkZXIsXG4gIEVuZHBvaW50XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEZldGNoUHJvdmlkZXIgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvZmV0Y2hfcHJvdmlkZXInO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcblxuZXhwb3J0IGNvbnN0IGVudW0gVG9rZW5UeXBlIHtcbiAgUkVGUkVTSF9UT0tFTiA9ICdSRUZSRVNIX1RPS0VOJyxcbiAgQUNDRVNTX1RPS0VOID0gJ0FDQ0VTU19UT0tFTidcbn1cblxuLyoqIFRoZSBzZXJ2ZXIgcmVzcG9uc2VzIHdpdGggc25ha2VfY2FzZTsgd2UgY29udmVydCB0byBjYW1lbENhc2UgKi9cbmludGVyZmFjZSBSZXF1ZXN0U3RzVG9rZW5TZXJ2ZXJSZXNwb25zZSB7XG4gIGFjY2Vzc190b2tlbjogc3RyaW5nO1xuICBleHBpcmVzX2luOiBzdHJpbmc7XG4gIHJlZnJlc2hfdG9rZW46IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0U3RzVG9rZW5SZXNwb25zZSB7XG4gIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gIGV4cGlyZXNJbjogc3RyaW5nO1xuICByZWZyZXNoVG9rZW46IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXZva2VUb2tlblJlcXVlc3Qge1xuICBwcm92aWRlcklkOiBzdHJpbmc7XG4gIHRva2VuVHlwZTogVG9rZW5UeXBlO1xuICB0b2tlbjogc3RyaW5nO1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJldm9rZVRva2VuUmVzcG9uc2Uge31cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlcXVlc3RTdHNUb2tlbihcbiAgYXV0aDogQXV0aCxcbiAgcmVmcmVzaFRva2VuOiBzdHJpbmdcbik6IFByb21pc2U8UmVxdWVzdFN0c1Rva2VuUmVzcG9uc2U+IHtcbiAgY29uc3QgcmVzcG9uc2UgPVxuICAgIGF3YWl0IF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZzxSZXF1ZXN0U3RzVG9rZW5TZXJ2ZXJSZXNwb25zZT4oXG4gICAgICBhdXRoLFxuICAgICAge30sXG4gICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBxdWVyeXN0cmluZyh7XG4gICAgICAgICAgJ2dyYW50X3R5cGUnOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgICAgJ3JlZnJlc2hfdG9rZW4nOiByZWZyZXNoVG9rZW5cbiAgICAgICAgfSkuc2xpY2UoMSk7XG4gICAgICAgIGNvbnN0IHsgdG9rZW5BcGlIb3N0LCBhcGlLZXkgfSA9IGF1dGguY29uZmlnO1xuICAgICAgICBjb25zdCB1cmwgPSBhd2FpdCBfZ2V0RmluYWxUYXJnZXQoXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICB0b2tlbkFwaUhvc3QsXG4gICAgICAgICAgRW5kcG9pbnQuVE9LRU4sXG4gICAgICAgICAgYGtleT0ke2FwaUtleX1gXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgaGVhZGVycyA9IGF3YWl0IChhdXRoIGFzIEF1dGhJbnRlcm5hbCkuX2dldEFkZGl0aW9uYWxIZWFkZXJzKCk7XG4gICAgICAgIGhlYWRlcnNbSHR0cEhlYWRlci5DT05URU5UX1RZUEVdID0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCc7XG5cbiAgICAgICAgY29uc3Qgb3B0aW9uczogUmVxdWVzdEluaXQgPSB7XG4gICAgICAgICAgbWV0aG9kOiBIdHRwTWV0aG9kLlBPU1QsXG4gICAgICAgICAgaGVhZGVycyxcbiAgICAgICAgICBib2R5XG4gICAgICAgIH07XG4gICAgICAgIGlmIChcbiAgICAgICAgICBhdXRoLmVtdWxhdG9yQ29uZmlnICYmXG4gICAgICAgICAgaXNDbG91ZFdvcmtzdGF0aW9uKGF1dGguZW11bGF0b3JDb25maWcuaG9zdClcbiAgICAgICAgKSB7XG4gICAgICAgICAgb3B0aW9ucy5jcmVkZW50aWFscyA9ICdpbmNsdWRlJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRmV0Y2hQcm92aWRlci5mZXRjaCgpKHVybCwgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgKTtcblxuICAvLyBUaGUgcmVzcG9uc2UgY29tZXMgYmFjayBpbiBzbmFrZV9jYXNlLiBDb252ZXJ0IHRvIGNhbWVsOlxuICByZXR1cm4ge1xuICAgIGFjY2Vzc1Rva2VuOiByZXNwb25zZS5hY2Nlc3NfdG9rZW4sXG4gICAgZXhwaXJlc0luOiByZXNwb25zZS5leHBpcmVzX2luLFxuICAgIHJlZnJlc2hUb2tlbjogcmVzcG9uc2UucmVmcmVzaF90b2tlblxuICB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmV2b2tlVG9rZW4oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFJldm9rZVRva2VuUmVxdWVzdFxuKTogUHJvbWlzZTxSZXZva2VUb2tlblJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8UmV2b2tlVG9rZW5SZXF1ZXN0LCBSZXZva2VUb2tlblJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5SRVZPS0VfVE9LRU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRmluYWxpemVNZmFSZXNwb25zZSB9IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9tZmEnO1xuaW1wb3J0IHsgcmVxdWVzdFN0c1Rva2VuIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL3Rva2VuJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBQZXJzaXN0ZWRCbG9iIH0gZnJvbSAnLi4vcGVyc2lzdGVuY2UnO1xuaW1wb3J0IHsgX2Fzc2VydCwgZGVidWdGYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgX3Rva2VuRXhwaXJlc0luIH0gZnJvbSAnLi9pZF90b2tlbl9yZXN1bHQnO1xuXG4vKipcbiAqIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGJlZm9yZSB0aGUgb2ZmaWNpYWwgZXhwaXJhdGlvbiB0aW1lIG9mIGEgdG9rZW5cbiAqIHRvIHJlZnJlc2ggdGhhdCB0b2tlbiwgdG8gcHJvdmlkZSBhIGJ1ZmZlciBmb3IgUlBDcyB0byBjb21wbGV0ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGVudW0gQnVmZmVyIHtcbiAgVE9LRU5fUkVGUkVTSCA9IDMwXzAwMFxufVxuXG4vKipcbiAqIFdlIG5lZWQgdG8gbWFyayB0aGlzIGNsYXNzIGFzIGludGVybmFsIGV4cGxpY2l0bHkgdG8gZXhjbHVkZSBpdCBpbiB0aGUgcHVibGljIHR5cGluZ3MsIGJlY2F1c2VcbiAqIGl0IHJlZmVyZW5jZXMgQXV0aEludGVybmFsIHdoaWNoIGhhcyBhIGNpcmN1bGFyIGRlcGVuZGVuY3kgd2l0aCBVc2VySW50ZXJuYWwuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHNUb2tlbk1hbmFnZXIge1xuICByZWZyZXNoVG9rZW46IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBhY2Nlc3NUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGV4cGlyYXRpb25UaW1lOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICBnZXQgaXNFeHBpcmVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICAhdGhpcy5leHBpcmF0aW9uVGltZSB8fFxuICAgICAgRGF0ZS5ub3coKSA+IHRoaXMuZXhwaXJhdGlvblRpbWUgLSBCdWZmZXIuVE9LRU5fUkVGUkVTSFxuICAgICk7XG4gIH1cblxuICB1cGRhdGVGcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgcmVzcG9uc2U6IElkVG9rZW5SZXNwb25zZSB8IEZpbmFsaXplTWZhUmVzcG9uc2VcbiAgKTogdm9pZCB7XG4gICAgX2Fzc2VydChyZXNwb25zZS5pZFRva2VuLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICBfYXNzZXJ0KFxuICAgICAgdHlwZW9mIHJlc3BvbnNlLmlkVG9rZW4gIT09ICd1bmRlZmluZWQnLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiByZXNwb25zZS5yZWZyZXNoVG9rZW4gIT09ICd1bmRlZmluZWQnLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgY29uc3QgZXhwaXJlc0luID1cbiAgICAgICdleHBpcmVzSW4nIGluIHJlc3BvbnNlICYmIHR5cGVvZiByZXNwb25zZS5leHBpcmVzSW4gIT09ICd1bmRlZmluZWQnXG4gICAgICAgID8gTnVtYmVyKHJlc3BvbnNlLmV4cGlyZXNJbilcbiAgICAgICAgOiBfdG9rZW5FeHBpcmVzSW4ocmVzcG9uc2UuaWRUb2tlbik7XG4gICAgdGhpcy51cGRhdGVUb2tlbnNBbmRFeHBpcmF0aW9uKFxuICAgICAgcmVzcG9uc2UuaWRUb2tlbixcbiAgICAgIHJlc3BvbnNlLnJlZnJlc2hUb2tlbixcbiAgICAgIGV4cGlyZXNJblxuICAgICk7XG4gIH1cblxuICB1cGRhdGVGcm9tSWRUb2tlbihpZFRva2VuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBfYXNzZXJ0KGlkVG9rZW4ubGVuZ3RoICE9PSAwLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICBjb25zdCBleHBpcmVzSW4gPSBfdG9rZW5FeHBpcmVzSW4oaWRUb2tlbik7XG4gICAgdGhpcy51cGRhdGVUb2tlbnNBbmRFeHBpcmF0aW9uKGlkVG9rZW4sIG51bGwsIGV4cGlyZXNJbik7XG4gIH1cblxuICBhc3luYyBnZXRUb2tlbihcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgZm9yY2VSZWZyZXNoID0gZmFsc2VcbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgaWYgKCFmb3JjZVJlZnJlc2ggJiYgdGhpcy5hY2Nlc3NUb2tlbiAmJiAhdGhpcy5pc0V4cGlyZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmFjY2Vzc1Rva2VuO1xuICAgIH1cblxuICAgIF9hc3NlcnQodGhpcy5yZWZyZXNoVG9rZW4sIGF1dGgsIEF1dGhFcnJvckNvZGUuVE9LRU5fRVhQSVJFRCk7XG5cbiAgICBpZiAodGhpcy5yZWZyZXNoVG9rZW4pIHtcbiAgICAgIGF3YWl0IHRoaXMucmVmcmVzaChhdXRoLCB0aGlzLnJlZnJlc2hUb2tlbiEpO1xuICAgICAgcmV0dXJuIHRoaXMuYWNjZXNzVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjbGVhclJlZnJlc2hUb2tlbigpOiB2b2lkIHtcbiAgICB0aGlzLnJlZnJlc2hUb2tlbiA9IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZnJlc2goYXV0aDogQXV0aEludGVybmFsLCBvbGRUb2tlbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBhY2Nlc3NUb2tlbiwgcmVmcmVzaFRva2VuLCBleHBpcmVzSW4gfSA9IGF3YWl0IHJlcXVlc3RTdHNUb2tlbihcbiAgICAgIGF1dGgsXG4gICAgICBvbGRUb2tlblxuICAgICk7XG4gICAgdGhpcy51cGRhdGVUb2tlbnNBbmRFeHBpcmF0aW9uKFxuICAgICAgYWNjZXNzVG9rZW4sXG4gICAgICByZWZyZXNoVG9rZW4sXG4gICAgICBOdW1iZXIoZXhwaXJlc0luKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVRva2Vuc0FuZEV4cGlyYXRpb24oXG4gICAgYWNjZXNzVG9rZW46IHN0cmluZyxcbiAgICByZWZyZXNoVG9rZW46IHN0cmluZyB8IG51bGwsXG4gICAgZXhwaXJlc0luU2VjOiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5yZWZyZXNoVG9rZW4gPSByZWZyZXNoVG9rZW4gfHwgbnVsbDtcbiAgICB0aGlzLmFjY2Vzc1Rva2VuID0gYWNjZXNzVG9rZW4gfHwgbnVsbDtcbiAgICB0aGlzLmV4cGlyYXRpb25UaW1lID0gRGF0ZS5ub3coKSArIGV4cGlyZXNJblNlYyAqIDEwMDA7XG4gIH1cblxuICBzdGF0aWMgZnJvbUpTT04oYXBwTmFtZTogc3RyaW5nLCBvYmplY3Q6IFBlcnNpc3RlZEJsb2IpOiBTdHNUb2tlbk1hbmFnZXIge1xuICAgIGNvbnN0IHsgcmVmcmVzaFRva2VuLCBhY2Nlc3NUb2tlbiwgZXhwaXJhdGlvblRpbWUgfSA9IG9iamVjdDtcblxuICAgIGNvbnN0IG1hbmFnZXIgPSBuZXcgU3RzVG9rZW5NYW5hZ2VyKCk7XG4gICAgaWYgKHJlZnJlc2hUb2tlbikge1xuICAgICAgX2Fzc2VydCh0eXBlb2YgcmVmcmVzaFRva2VuID09PSAnc3RyaW5nJywgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUiwge1xuICAgICAgICBhcHBOYW1lXG4gICAgICB9KTtcbiAgICAgIG1hbmFnZXIucmVmcmVzaFRva2VuID0gcmVmcmVzaFRva2VuO1xuICAgIH1cbiAgICBpZiAoYWNjZXNzVG9rZW4pIHtcbiAgICAgIF9hc3NlcnQodHlwZW9mIGFjY2Vzc1Rva2VuID09PSAnc3RyaW5nJywgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUiwge1xuICAgICAgICBhcHBOYW1lXG4gICAgICB9KTtcbiAgICAgIG1hbmFnZXIuYWNjZXNzVG9rZW4gPSBhY2Nlc3NUb2tlbjtcbiAgICB9XG4gICAgaWYgKGV4cGlyYXRpb25UaW1lKSB7XG4gICAgICBfYXNzZXJ0KFxuICAgICAgICB0eXBlb2YgZXhwaXJhdGlvblRpbWUgPT09ICdudW1iZXInLFxuICAgICAgICBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuICAgICAgICB7XG4gICAgICAgICAgYXBwTmFtZVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgbWFuYWdlci5leHBpcmF0aW9uVGltZSA9IGV4cGlyYXRpb25UaW1lO1xuICAgIH1cbiAgICByZXR1cm4gbWFuYWdlcjtcbiAgfVxuXG4gIHRvSlNPTigpOiBvYmplY3Qge1xuICAgIHJldHVybiB7XG4gICAgICByZWZyZXNoVG9rZW46IHRoaXMucmVmcmVzaFRva2VuLFxuICAgICAgYWNjZXNzVG9rZW46IHRoaXMuYWNjZXNzVG9rZW4sXG4gICAgICBleHBpcmF0aW9uVGltZTogdGhpcy5leHBpcmF0aW9uVGltZVxuICAgIH07XG4gIH1cblxuICBfYXNzaWduKHN0c1Rva2VuTWFuYWdlcjogU3RzVG9rZW5NYW5hZ2VyKTogdm9pZCB7XG4gICAgdGhpcy5hY2Nlc3NUb2tlbiA9IHN0c1Rva2VuTWFuYWdlci5hY2Nlc3NUb2tlbjtcbiAgICB0aGlzLnJlZnJlc2hUb2tlbiA9IHN0c1Rva2VuTWFuYWdlci5yZWZyZXNoVG9rZW47XG4gICAgdGhpcy5leHBpcmF0aW9uVGltZSA9IHN0c1Rva2VuTWFuYWdlci5leHBpcmF0aW9uVGltZTtcbiAgfVxuXG4gIF9jbG9uZSgpOiBTdHNUb2tlbk1hbmFnZXIge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBTdHNUb2tlbk1hbmFnZXIoKSwgdGhpcy50b0pTT04oKSk7XG4gIH1cblxuICBfcGVyZm9ybVJlZnJlc2goKTogbmV2ZXIge1xuICAgIHJldHVybiBkZWJ1Z0ZhaWwoJ25vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgSWRUb2tlblJlc3VsdCwgVXNlckluZm8gfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgTmV4dEZuIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHtcbiAgQVBJVXNlckluZm8sXG4gIEdldEFjY291bnRJbmZvUmVzcG9uc2UsXG4gIGRlbGV0ZUFjY291bnRcbn0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IEZpbmFsaXplTWZhUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHtcbiAgTXV0YWJsZVVzZXJJbmZvLFxuICBVc2VySW50ZXJuYWwsXG4gIFVzZXJQYXJhbWV0ZXJzXG59IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBQZXJzaXN0ZWRCbG9iIH0gZnJvbSAnLi4vcGVyc2lzdGVuY2UnO1xuaW1wb3J0IHtcbiAgX2Fzc2VydCxcbiAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3Jcbn0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgZ2V0SWRUb2tlblJlc3VsdCB9IGZyb20gJy4vaWRfdG9rZW5fcmVzdWx0JztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgUHJvYWN0aXZlUmVmcmVzaCB9IGZyb20gJy4vcHJvYWN0aXZlX3JlZnJlc2gnO1xuaW1wb3J0IHsgZXh0cmFjdFByb3ZpZGVyRGF0YSwgX3JlbG9hZFdpdGhvdXRTYXZpbmcsIHJlbG9hZCB9IGZyb20gJy4vcmVsb2FkJztcbmltcG9ydCB7IFN0c1Rva2VuTWFuYWdlciB9IGZyb20gJy4vdG9rZW5fbWFuYWdlcic7XG5pbXBvcnQgeyBVc2VyTWV0YWRhdGEgfSBmcm9tICcuL3VzZXJfbWV0YWRhdGEnO1xuaW1wb3J0IHsgUHJvdmlkZXJJZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5cbmZ1bmN0aW9uIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKFxuICBhc3NlcnRpb246IHVua25vd24sXG4gIGFwcE5hbWU6IHN0cmluZ1xuKTogYXNzZXJ0cyBhc3NlcnRpb24gaXMgc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgX2Fzc2VydChcbiAgICB0eXBlb2YgYXNzZXJ0aW9uID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgYXNzZXJ0aW9uID09PSAndW5kZWZpbmVkJyxcbiAgICBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuICAgIHsgYXBwTmFtZSB9XG4gICk7XG59XG5cbmV4cG9ydCBjbGFzcyBVc2VySW1wbCBpbXBsZW1lbnRzIFVzZXJJbnRlcm5hbCB7XG4gIC8vIEZvciB0aGUgdXNlciBvYmplY3QsIHByb3ZpZGVyIGlzIGFsd2F5cyBGaXJlYmFzZS5cbiAgcmVhZG9ubHkgcHJvdmlkZXJJZCA9IFByb3ZpZGVySWQuRklSRUJBU0U7XG4gIHN0c1Rva2VuTWFuYWdlcjogU3RzVG9rZW5NYW5hZ2VyO1xuICAvLyBMYXN0IGtub3duIGFjY2Vzc1Rva2VuIHNvIHdlIGtub3cgd2hlbiBpdCBjaGFuZ2VzXG4gIHByaXZhdGUgYWNjZXNzVG9rZW46IHN0cmluZyB8IG51bGw7XG5cbiAgdWlkOiBzdHJpbmc7XG4gIGF1dGg6IEF1dGhJbnRlcm5hbDtcbiAgZW1haWxWZXJpZmllZDogYm9vbGVhbjtcbiAgaXNBbm9ueW1vdXM6IGJvb2xlYW47XG4gIHRlbmFudElkOiBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBtZXRhZGF0YTogVXNlck1ldGFkYXRhO1xuICBwcm92aWRlckRhdGE6IE11dGFibGVVc2VySW5mb1tdO1xuXG4gIC8vIE9wdGlvbmFsIGZpZWxkcyBmcm9tIFVzZXJJbmZvXG4gIGRpc3BsYXlOYW1lOiBzdHJpbmcgfCBudWxsO1xuICBlbWFpbDogc3RyaW5nIHwgbnVsbDtcbiAgcGhvbmVOdW1iZXI6IHN0cmluZyB8IG51bGw7XG4gIHBob3RvVVJMOiBzdHJpbmcgfCBudWxsO1xuXG4gIF9yZWRpcmVjdEV2ZW50SWQ/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvYWN0aXZlUmVmcmVzaCA9IG5ldyBQcm9hY3RpdmVSZWZyZXNoKHRoaXMpO1xuXG4gIGNvbnN0cnVjdG9yKHsgdWlkLCBhdXRoLCBzdHNUb2tlbk1hbmFnZXIsIC4uLm9wdCB9OiBVc2VyUGFyYW1ldGVycykge1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMuYXV0aCA9IGF1dGg7XG4gICAgdGhpcy5zdHNUb2tlbk1hbmFnZXIgPSBzdHNUb2tlbk1hbmFnZXI7XG4gICAgdGhpcy5hY2Nlc3NUb2tlbiA9IHN0c1Rva2VuTWFuYWdlci5hY2Nlc3NUb2tlbjtcbiAgICB0aGlzLmRpc3BsYXlOYW1lID0gb3B0LmRpc3BsYXlOYW1lIHx8IG51bGw7XG4gICAgdGhpcy5lbWFpbCA9IG9wdC5lbWFpbCB8fCBudWxsO1xuICAgIHRoaXMuZW1haWxWZXJpZmllZCA9IG9wdC5lbWFpbFZlcmlmaWVkIHx8IGZhbHNlO1xuICAgIHRoaXMucGhvbmVOdW1iZXIgPSBvcHQucGhvbmVOdW1iZXIgfHwgbnVsbDtcbiAgICB0aGlzLnBob3RvVVJMID0gb3B0LnBob3RvVVJMIHx8IG51bGw7XG4gICAgdGhpcy5pc0Fub255bW91cyA9IG9wdC5pc0Fub255bW91cyB8fCBmYWxzZTtcbiAgICB0aGlzLnRlbmFudElkID0gb3B0LnRlbmFudElkIHx8IG51bGw7XG4gICAgdGhpcy5wcm92aWRlckRhdGEgPSBvcHQucHJvdmlkZXJEYXRhID8gWy4uLm9wdC5wcm92aWRlckRhdGFdIDogW107XG4gICAgdGhpcy5tZXRhZGF0YSA9IG5ldyBVc2VyTWV0YWRhdGEoXG4gICAgICBvcHQuY3JlYXRlZEF0IHx8IHVuZGVmaW5lZCxcbiAgICAgIG9wdC5sYXN0TG9naW5BdCB8fCB1bmRlZmluZWRcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgZ2V0SWRUb2tlbihmb3JjZVJlZnJlc2g/OiBib29sZWFuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgICAgdGhpcyxcbiAgICAgIHRoaXMuc3RzVG9rZW5NYW5hZ2VyLmdldFRva2VuKHRoaXMuYXV0aCwgZm9yY2VSZWZyZXNoKVxuICAgICk7XG4gICAgX2Fzc2VydChhY2Nlc3NUb2tlbiwgdGhpcy5hdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcblxuICAgIGlmICh0aGlzLmFjY2Vzc1Rva2VuICE9PSBhY2Nlc3NUb2tlbikge1xuICAgICAgdGhpcy5hY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuO1xuICAgICAgYXdhaXQgdGhpcy5hdXRoLl9wZXJzaXN0VXNlcklmQ3VycmVudCh0aGlzKTtcbiAgICAgIHRoaXMuYXV0aC5fbm90aWZ5TGlzdGVuZXJzSWZDdXJyZW50KHRoaXMpO1xuICAgIH1cblxuICAgIHJldHVybiBhY2Nlc3NUb2tlbjtcbiAgfVxuXG4gIGdldElkVG9rZW5SZXN1bHQoZm9yY2VSZWZyZXNoPzogYm9vbGVhbik6IFByb21pc2U8SWRUb2tlblJlc3VsdD4ge1xuICAgIHJldHVybiBnZXRJZFRva2VuUmVzdWx0KHRoaXMsIGZvcmNlUmVmcmVzaCk7XG4gIH1cblxuICByZWxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHJlbG9hZCh0aGlzKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVsb2FkVXNlckluZm86IEFQSVVzZXJJbmZvIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVsb2FkTGlzdGVuZXI6IE5leHRGbjxBUElVc2VySW5mbz4gfCBudWxsID0gbnVsbDtcblxuICBfYXNzaWduKHVzZXI6IFVzZXJJbnRlcm5hbCk6IHZvaWQge1xuICAgIGlmICh0aGlzID09PSB1c2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIF9hc3NlcnQodGhpcy51aWQgPT09IHVzZXIudWlkLCB0aGlzLmF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIHRoaXMuZGlzcGxheU5hbWUgPSB1c2VyLmRpc3BsYXlOYW1lO1xuICAgIHRoaXMucGhvdG9VUkwgPSB1c2VyLnBob3RvVVJMO1xuICAgIHRoaXMuZW1haWwgPSB1c2VyLmVtYWlsO1xuICAgIHRoaXMuZW1haWxWZXJpZmllZCA9IHVzZXIuZW1haWxWZXJpZmllZDtcbiAgICB0aGlzLnBob25lTnVtYmVyID0gdXNlci5waG9uZU51bWJlcjtcbiAgICB0aGlzLmlzQW5vbnltb3VzID0gdXNlci5pc0Fub255bW91cztcbiAgICB0aGlzLnRlbmFudElkID0gdXNlci50ZW5hbnRJZDtcbiAgICB0aGlzLnByb3ZpZGVyRGF0YSA9IHVzZXIucHJvdmlkZXJEYXRhLm1hcCh1c2VySW5mbyA9PiAoeyAuLi51c2VySW5mbyB9KSk7XG4gICAgdGhpcy5tZXRhZGF0YS5fY29weSh1c2VyLm1ldGFkYXRhKTtcbiAgICB0aGlzLnN0c1Rva2VuTWFuYWdlci5fYXNzaWduKHVzZXIuc3RzVG9rZW5NYW5hZ2VyKTtcbiAgfVxuXG4gIF9jbG9uZShhdXRoOiBBdXRoSW50ZXJuYWwpOiBVc2VySW50ZXJuYWwge1xuICAgIGNvbnN0IG5ld1VzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgLi4udGhpcyxcbiAgICAgIGF1dGgsXG4gICAgICBzdHNUb2tlbk1hbmFnZXI6IHRoaXMuc3RzVG9rZW5NYW5hZ2VyLl9jbG9uZSgpXG4gICAgfSk7XG4gICAgbmV3VXNlci5tZXRhZGF0YS5fY29weSh0aGlzLm1ldGFkYXRhKTtcbiAgICByZXR1cm4gbmV3VXNlcjtcbiAgfVxuXG4gIF9vblJlbG9hZChjYWxsYmFjazogTmV4dEZuPEFQSVVzZXJJbmZvPik6IHZvaWQge1xuICAgIC8vIFRoZXJlIHNob3VsZCBvbmx5IGV2ZXIgYmUgb25lIGxpc3RlbmVyLCBhbmQgdGhhdCBpcyBhIHNpbmdsZSBpbnN0YW5jZSBvZiBNdWx0aUZhY3RvclVzZXJcbiAgICBfYXNzZXJ0KCF0aGlzLnJlbG9hZExpc3RlbmVyLCB0aGlzLmF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIHRoaXMucmVsb2FkTGlzdGVuZXIgPSBjYWxsYmFjaztcbiAgICBpZiAodGhpcy5yZWxvYWRVc2VySW5mbykge1xuICAgICAgdGhpcy5fbm90aWZ5UmVsb2FkTGlzdGVuZXIodGhpcy5yZWxvYWRVc2VySW5mbyk7XG4gICAgICB0aGlzLnJlbG9hZFVzZXJJbmZvID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBfbm90aWZ5UmVsb2FkTGlzdGVuZXIodXNlckluZm86IEFQSVVzZXJJbmZvKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVsb2FkTGlzdGVuZXIpIHtcbiAgICAgIHRoaXMucmVsb2FkTGlzdGVuZXIodXNlckluZm8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiBubyBsaXN0ZW5lciBpcyBzdWJzY3JpYmVkIHlldCwgc2F2ZSB0aGUgcmVzdWx0IHNvIGl0J3MgYXZhaWxhYmxlIHdoZW4gdGhleSBkbyBzdWJzY3JpYmVcbiAgICAgIHRoaXMucmVsb2FkVXNlckluZm8gPSB1c2VySW5mbztcbiAgICB9XG4gIH1cblxuICBfc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMucHJvYWN0aXZlUmVmcmVzaC5fc3RhcnQoKTtcbiAgfVxuXG4gIF9zdG9wUHJvYWN0aXZlUmVmcmVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLnByb2FjdGl2ZVJlZnJlc2guX3N0b3AoKTtcbiAgfVxuXG4gIGFzeW5jIF91cGRhdGVUb2tlbnNJZk5lY2Vzc2FyeShcbiAgICByZXNwb25zZTogSWRUb2tlblJlc3BvbnNlIHwgRmluYWxpemVNZmFSZXNwb25zZSxcbiAgICByZWxvYWQgPSBmYWxzZVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgdG9rZW5zUmVmcmVzaGVkID0gZmFsc2U7XG4gICAgaWYgKFxuICAgICAgcmVzcG9uc2UuaWRUb2tlbiAmJlxuICAgICAgcmVzcG9uc2UuaWRUb2tlbiAhPT0gdGhpcy5zdHNUb2tlbk1hbmFnZXIuYWNjZXNzVG9rZW5cbiAgICApIHtcbiAgICAgIHRoaXMuc3RzVG9rZW5NYW5hZ2VyLnVwZGF0ZUZyb21TZXJ2ZXJSZXNwb25zZShyZXNwb25zZSk7XG4gICAgICB0b2tlbnNSZWZyZXNoZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZWxvYWQpIHtcbiAgICAgIGF3YWl0IF9yZWxvYWRXaXRob3V0U2F2aW5nKHRoaXMpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuYXV0aC5fcGVyc2lzdFVzZXJJZkN1cnJlbnQodGhpcyk7XG4gICAgaWYgKHRva2Vuc1JlZnJlc2hlZCkge1xuICAgICAgdGhpcy5hdXRoLl9ub3RpZnlMaXN0ZW5lcnNJZkN1cnJlbnQodGhpcyk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZGVsZXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmF1dGguYXBwKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcih0aGlzLmF1dGgpXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBpZFRva2VuID0gYXdhaXQgdGhpcy5nZXRJZFRva2VuKCk7XG4gICAgYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQodGhpcywgZGVsZXRlQWNjb3VudCh0aGlzLmF1dGgsIHsgaWRUb2tlbiB9KSk7XG4gICAgdGhpcy5zdHNUb2tlbk1hbmFnZXIuY2xlYXJSZWZyZXNoVG9rZW4oKTtcblxuICAgIC8vIFRPRE86IERldGVybWluZSBpZiBjYW5jZWxsYWJsZS1wcm9taXNlcyBhcmUgbmVjZXNzYXJ5IHRvIHVzZSBpbiB0aGlzIGNsYXNzIHNvIHRoYXQgZGVsZXRlKClcbiAgICAvLyAgICAgICBjYW5jZWxzIHBlbmRpbmcgYWN0aW9ucy4uLlxuXG4gICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduT3V0KCk7XG4gIH1cblxuICB0b0pTT04oKTogUGVyc2lzdGVkQmxvYiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVpZDogdGhpcy51aWQsXG4gICAgICBlbWFpbDogdGhpcy5lbWFpbCB8fCB1bmRlZmluZWQsXG4gICAgICBlbWFpbFZlcmlmaWVkOiB0aGlzLmVtYWlsVmVyaWZpZWQsXG4gICAgICBkaXNwbGF5TmFtZTogdGhpcy5kaXNwbGF5TmFtZSB8fCB1bmRlZmluZWQsXG4gICAgICBpc0Fub255bW91czogdGhpcy5pc0Fub255bW91cyxcbiAgICAgIHBob3RvVVJMOiB0aGlzLnBob3RvVVJMIHx8IHVuZGVmaW5lZCxcbiAgICAgIHBob25lTnVtYmVyOiB0aGlzLnBob25lTnVtYmVyIHx8IHVuZGVmaW5lZCxcbiAgICAgIHRlbmFudElkOiB0aGlzLnRlbmFudElkIHx8IHVuZGVmaW5lZCxcbiAgICAgIHByb3ZpZGVyRGF0YTogdGhpcy5wcm92aWRlckRhdGEubWFwKHVzZXJJbmZvID0+ICh7IC4uLnVzZXJJbmZvIH0pKSxcbiAgICAgIHN0c1Rva2VuTWFuYWdlcjogdGhpcy5zdHNUb2tlbk1hbmFnZXIudG9KU09OKCksXG4gICAgICAvLyBSZWRpcmVjdCBldmVudCBJRCBtdXN0IGJlIG1haW50YWluZWQgaW4gY2FzZSB0aGVyZSBpcyBhIHBlbmRpbmdcbiAgICAgIC8vIHJlZGlyZWN0IGV2ZW50LlxuICAgICAgX3JlZGlyZWN0RXZlbnRJZDogdGhpcy5fcmVkaXJlY3RFdmVudElkLFxuICAgICAgLi4udGhpcy5tZXRhZGF0YS50b0pTT04oKSxcblxuICAgICAgLy8gUmVxdWlyZWQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCB0aGUgbGVnYWN5IFNESyAoZ28vZmlyZWJhc2UtYXV0aC1zZGstcGVyc2lzdGVuY2UtcGFyc2luZyk6XG4gICAgICBhcGlLZXk6IHRoaXMuYXV0aC5jb25maWcuYXBpS2V5LFxuICAgICAgYXBwTmFtZTogdGhpcy5hdXRoLm5hbWVcbiAgICAgIC8vIE1pc3NpbmcgYXV0aERvbWFpbiB3aWxsIGJlIHRvbGVyYXRlZCBieSB0aGUgbGVnYWN5IFNESy5cbiAgICAgIC8vIHN0c1Rva2VuTWFuYWdlci5hcGlLZXkgaXNuJ3QgYWN0dWFsbHkgcmVxdWlyZWQgKGRlc3BpdGUgdGhlIGxlZ2FjeSBTREsgcGVyc2lzdGluZyBpdCkuXG4gICAgfTtcbiAgfVxuXG4gIGdldCByZWZyZXNoVG9rZW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zdHNUb2tlbk1hbmFnZXIucmVmcmVzaFRva2VuIHx8ICcnO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tSlNPTihhdXRoOiBBdXRoSW50ZXJuYWwsIG9iamVjdDogUGVyc2lzdGVkQmxvYik6IFVzZXJJbnRlcm5hbCB7XG4gICAgY29uc3QgZGlzcGxheU5hbWUgPSBvYmplY3QuZGlzcGxheU5hbWUgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGVtYWlsID0gb2JqZWN0LmVtYWlsID8/IHVuZGVmaW5lZDtcbiAgICBjb25zdCBwaG9uZU51bWJlciA9IG9iamVjdC5waG9uZU51bWJlciA/PyB1bmRlZmluZWQ7XG4gICAgY29uc3QgcGhvdG9VUkwgPSBvYmplY3QucGhvdG9VUkwgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRlbmFudElkID0gb2JqZWN0LnRlbmFudElkID8/IHVuZGVmaW5lZDtcbiAgICBjb25zdCBfcmVkaXJlY3RFdmVudElkID0gb2JqZWN0Ll9yZWRpcmVjdEV2ZW50SWQgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGNyZWF0ZWRBdCA9IG9iamVjdC5jcmVhdGVkQXQgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGxhc3RMb2dpbkF0ID0gb2JqZWN0Lmxhc3RMb2dpbkF0ID8/IHVuZGVmaW5lZDtcbiAgICBjb25zdCB7XG4gICAgICB1aWQsXG4gICAgICBlbWFpbFZlcmlmaWVkLFxuICAgICAgaXNBbm9ueW1vdXMsXG4gICAgICBwcm92aWRlckRhdGEsXG4gICAgICBzdHNUb2tlbk1hbmFnZXI6IHBsYWluT2JqZWN0VG9rZW5NYW5hZ2VyXG4gICAgfSA9IG9iamVjdDtcblxuICAgIF9hc3NlcnQodWlkICYmIHBsYWluT2JqZWN0VG9rZW5NYW5hZ2VyLCBhdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcblxuICAgIGNvbnN0IHN0c1Rva2VuTWFuYWdlciA9IFN0c1Rva2VuTWFuYWdlci5mcm9tSlNPTihcbiAgICAgIHRoaXMubmFtZSxcbiAgICAgIHBsYWluT2JqZWN0VG9rZW5NYW5hZ2VyIGFzIFBlcnNpc3RlZEJsb2JcbiAgICApO1xuXG4gICAgX2Fzc2VydCh0eXBlb2YgdWlkID09PSAnc3RyaW5nJywgYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgYXNzZXJ0U3RyaW5nT3JVbmRlZmluZWQoZGlzcGxheU5hbWUsIGF1dGgubmFtZSk7XG4gICAgYXNzZXJ0U3RyaW5nT3JVbmRlZmluZWQoZW1haWwsIGF1dGgubmFtZSk7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiBlbWFpbFZlcmlmaWVkID09PSAnYm9vbGVhbicsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiBpc0Fub255bW91cyA9PT0gJ2Jvb2xlYW4nLFxuICAgICAgYXV0aCxcbiAgICAgIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JcbiAgICApO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKHBob25lTnVtYmVyLCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKHBob3RvVVJMLCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKHRlbmFudElkLCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKF9yZWRpcmVjdEV2ZW50SWQsIGF1dGgubmFtZSk7XG4gICAgYXNzZXJ0U3RyaW5nT3JVbmRlZmluZWQoY3JlYXRlZEF0LCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKGxhc3RMb2dpbkF0LCBhdXRoLm5hbWUpO1xuICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgdWlkLFxuICAgICAgYXV0aCxcbiAgICAgIGVtYWlsLFxuICAgICAgZW1haWxWZXJpZmllZCxcbiAgICAgIGRpc3BsYXlOYW1lLFxuICAgICAgaXNBbm9ueW1vdXMsXG4gICAgICBwaG90b1VSTCxcbiAgICAgIHBob25lTnVtYmVyLFxuICAgICAgdGVuYW50SWQsXG4gICAgICBzdHNUb2tlbk1hbmFnZXIsXG4gICAgICBjcmVhdGVkQXQsXG4gICAgICBsYXN0TG9naW5BdFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3ZpZGVyRGF0YSAmJiBBcnJheS5pc0FycmF5KHByb3ZpZGVyRGF0YSkpIHtcbiAgICAgIHVzZXIucHJvdmlkZXJEYXRhID0gcHJvdmlkZXJEYXRhLm1hcCh1c2VySW5mbyA9PiAoeyAuLi51c2VySW5mbyB9KSk7XG4gICAgfVxuXG4gICAgaWYgKF9yZWRpcmVjdEV2ZW50SWQpIHtcbiAgICAgIHVzZXIuX3JlZGlyZWN0RXZlbnRJZCA9IF9yZWRpcmVjdEV2ZW50SWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVzZXI7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBhIFVzZXIgZnJvbSBhbiBpZFRva2VuIHNlcnZlciByZXNwb25zZVxuICAgKiBAcGFyYW0gYXV0aFxuICAgKiBAcGFyYW0gaWRUb2tlblJlc3BvbnNlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgX2Zyb21JZFRva2VuUmVzcG9uc2UoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGlkVG9rZW5SZXNwb25zZTogSWRUb2tlblJlc3BvbnNlLFxuICAgIGlzQW5vbnltb3VzOiBib29sZWFuID0gZmFsc2VcbiAgKTogUHJvbWlzZTxVc2VySW50ZXJuYWw+IHtcbiAgICBjb25zdCBzdHNUb2tlbk1hbmFnZXIgPSBuZXcgU3RzVG9rZW5NYW5hZ2VyKCk7XG4gICAgc3RzVG9rZW5NYW5hZ2VyLnVwZGF0ZUZyb21TZXJ2ZXJSZXNwb25zZShpZFRva2VuUmVzcG9uc2UpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgRmlyZWJhc2UgQXV0aCB1c2VyLlxuICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgdWlkOiBpZFRva2VuUmVzcG9uc2UubG9jYWxJZCxcbiAgICAgIGF1dGgsXG4gICAgICBzdHNUb2tlbk1hbmFnZXIsXG4gICAgICBpc0Fub255bW91c1xuICAgIH0pO1xuXG4gICAgLy8gVXBkYXRlcyB0aGUgdXNlciBpbmZvIGFuZCBkYXRhIGFuZCByZXNvbHZlcyB3aXRoIGEgdXNlciBpbnN0YW5jZS5cbiAgICBhd2FpdCBfcmVsb2FkV2l0aG91dFNhdmluZyh1c2VyKTtcbiAgICByZXR1cm4gdXNlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGEgVXNlciBmcm9tIGFuIGlkVG9rZW4gc2VydmVyIHJlc3BvbnNlXG4gICAqIEBwYXJhbSBhdXRoXG4gICAqIEBwYXJhbSBpZFRva2VuUmVzcG9uc2VcbiAgICovXG4gIHN0YXRpYyBhc3luYyBfZnJvbUdldEFjY291bnRJbmZvUmVzcG9uc2UoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIHJlc3BvbnNlOiBHZXRBY2NvdW50SW5mb1Jlc3BvbnNlLFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPFVzZXJJbnRlcm5hbD4ge1xuICAgIGNvbnN0IGNvcmVBY2NvdW50ID0gcmVzcG9uc2UudXNlcnNbMF07XG4gICAgX2Fzc2VydChjb3JlQWNjb3VudC5sb2NhbElkICE9PSB1bmRlZmluZWQsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuXG4gICAgY29uc3QgcHJvdmlkZXJEYXRhOiBVc2VySW5mb1tdID1cbiAgICAgIGNvcmVBY2NvdW50LnByb3ZpZGVyVXNlckluZm8gIT09IHVuZGVmaW5lZFxuICAgICAgICA/IGV4dHJhY3RQcm92aWRlckRhdGEoY29yZUFjY291bnQucHJvdmlkZXJVc2VySW5mbylcbiAgICAgICAgOiBbXTtcblxuICAgIGNvbnN0IGlzQW5vbnltb3VzID1cbiAgICAgICEoY29yZUFjY291bnQuZW1haWwgJiYgY29yZUFjY291bnQucGFzc3dvcmRIYXNoKSAmJiAhcHJvdmlkZXJEYXRhPy5sZW5ndGg7XG5cbiAgICBjb25zdCBzdHNUb2tlbk1hbmFnZXIgPSBuZXcgU3RzVG9rZW5NYW5hZ2VyKCk7XG4gICAgc3RzVG9rZW5NYW5hZ2VyLnVwZGF0ZUZyb21JZFRva2VuKGlkVG9rZW4pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgRmlyZWJhc2UgQXV0aCB1c2VyLlxuICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgdWlkOiBjb3JlQWNjb3VudC5sb2NhbElkLFxuICAgICAgYXV0aCxcbiAgICAgIHN0c1Rva2VuTWFuYWdlcixcbiAgICAgIGlzQW5vbnltb3VzXG4gICAgfSk7XG5cbiAgICAvLyB1cGRhdGUgdGhlIHVzZXIgd2l0aCBkYXRhIGZyb20gdGhlIEdldEFjY291bnRJbmZvIHJlc3BvbnNlLlxuICAgIGNvbnN0IHVwZGF0ZXM6IFBhcnRpYWw8VXNlckludGVybmFsPiA9IHtcbiAgICAgIHVpZDogY29yZUFjY291bnQubG9jYWxJZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBjb3JlQWNjb3VudC5kaXNwbGF5TmFtZSB8fCBudWxsLFxuICAgICAgcGhvdG9VUkw6IGNvcmVBY2NvdW50LnBob3RvVXJsIHx8IG51bGwsXG4gICAgICBlbWFpbDogY29yZUFjY291bnQuZW1haWwgfHwgbnVsbCxcbiAgICAgIGVtYWlsVmVyaWZpZWQ6IGNvcmVBY2NvdW50LmVtYWlsVmVyaWZpZWQgfHwgZmFsc2UsXG4gICAgICBwaG9uZU51bWJlcjogY29yZUFjY291bnQucGhvbmVOdW1iZXIgfHwgbnVsbCxcbiAgICAgIHRlbmFudElkOiBjb3JlQWNjb3VudC50ZW5hbnRJZCB8fCBudWxsLFxuICAgICAgcHJvdmlkZXJEYXRhLFxuICAgICAgbWV0YWRhdGE6IG5ldyBVc2VyTWV0YWRhdGEoXG4gICAgICAgIGNvcmVBY2NvdW50LmNyZWF0ZWRBdCxcbiAgICAgICAgY29yZUFjY291bnQubGFzdExvZ2luQXRcbiAgICAgICksXG4gICAgICBpc0Fub255bW91czpcbiAgICAgICAgIShjb3JlQWNjb3VudC5lbWFpbCAmJiBjb3JlQWNjb3VudC5wYXNzd29yZEhhc2gpICYmXG4gICAgICAgICFwcm92aWRlckRhdGE/Lmxlbmd0aFxuICAgIH07XG5cbiAgICBPYmplY3QuYXNzaWduKHVzZXIsIHVwZGF0ZXMpO1xuICAgIHJldHVybiB1c2VyO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgZGVidWdBc3NlcnQgfSBmcm9tICcuL2Fzc2VydCc7XG5cbi8qKlxuICogT3VyIEFQSSBoYXMgYSBsb3Qgb2Ygb25lLW9mZiBjb25zdGFudHMgdGhhdCBhcmUgdXNlZCB0byBkbyB0aGluZ3MuXG4gKiBVbmZvcnR1bmF0ZWx5IHdlIGNhbid0IGV4cG9ydCB0aGVzZSBhcyBjbGFzc2VzIGluc3RhbnRpYXRlZCBkaXJlY3RseSBzaW5jZVxuICogdGhlIGNvbnN0cnVjdG9yIG1heSBzaWRlIGVmZmVjdCBhbmQgdGhlcmVmb3JlIGNhbid0IGJlIHByb3ZlbiB0byBiZSBzYWZlbHlcbiAqIGN1bGxlZC4gSW5zdGVhZCwgd2UgZXhwb3J0IHRoZXNlIGNsYXNzZXMgdGhlbXNlbHZlcyBhcyBhIGxvd2VyQ2FtZWxDYXNlXG4gKiBjb25zdGFudCwgYW5kIGluc3RhbnRpYXRlIHRoZW0gdW5kZXIgdGhlIGhvb2QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2luZ2xldG9uSW5zdGFudGlhdG9yPFQ+IHtcbiAgbmV3ICgpOiBUO1xufVxuXG5jb25zdCBpbnN0YW5jZUNhY2hlOiBNYXA8dW5rbm93biwgdW5rbm93bj4gPSBuZXcgTWFwKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBfZ2V0SW5zdGFuY2U8VD4oY2xzOiB1bmtub3duKTogVCB7XG4gIGRlYnVnQXNzZXJ0KGNscyBpbnN0YW5jZW9mIEZ1bmN0aW9uLCAnRXhwZWN0ZWQgYSBjbGFzcyBkZWZpbml0aW9uJyk7XG4gIGxldCBpbnN0YW5jZSA9IGluc3RhbmNlQ2FjaGUuZ2V0KGNscykgYXMgVCB8IHVuZGVmaW5lZDtcblxuICBpZiAoaW5zdGFuY2UpIHtcbiAgICBkZWJ1Z0Fzc2VydChcbiAgICAgIGluc3RhbmNlIGluc3RhbmNlb2YgY2xzLFxuICAgICAgJ0luc3RhbmNlIHN0b3JlZCBpbiBjYWNoZSBtaXNtYXRjaGVkIHdpdGggY2xhc3MnXG4gICAgKTtcbiAgICByZXR1cm4gaW5zdGFuY2U7XG4gIH1cblxuICBpbnN0YW5jZSA9IG5ldyAoY2xzIGFzIFNpbmdsZXRvbkluc3RhbnRpYXRvcjxUPikoKTtcbiAgaW5zdGFuY2VDYWNoZS5zZXQoY2xzLCBpbnN0YW5jZSk7XG4gIHJldHVybiBpbnN0YW5jZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9jbGVhckluc3RhbmNlTWFwKCk6IHZvaWQge1xuICBpbnN0YW5jZUNhY2hlLmNsZWFyKCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUGVyc2lzdGVuY2UgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQge1xuICBQZXJzaXN0ZW5jZUludGVybmFsLFxuICBQZXJzaXN0ZW5jZVR5cGUsXG4gIFBlcnNpc3RlbmNlVmFsdWUsXG4gIFN0b3JhZ2VFdmVudExpc3RlbmVyXG59IGZyb20gJy4uL3BlcnNpc3RlbmNlJztcblxuZXhwb3J0IGNsYXNzIEluTWVtb3J5UGVyc2lzdGVuY2UgaW1wbGVtZW50cyBQZXJzaXN0ZW5jZUludGVybmFsIHtcbiAgc3RhdGljIHR5cGU6ICdOT05FJyA9ICdOT05FJztcbiAgcmVhZG9ubHkgdHlwZSA9IFBlcnNpc3RlbmNlVHlwZS5OT05FO1xuICBzdG9yYWdlOiBSZWNvcmQ8c3RyaW5nLCBQZXJzaXN0ZW5jZVZhbHVlPiA9IHt9O1xuXG4gIGFzeW5jIF9pc0F2YWlsYWJsZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIF9zZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBQZXJzaXN0ZW5jZVZhbHVlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zdG9yYWdlW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGFzeW5jIF9nZXQ8VCBleHRlbmRzIFBlcnNpc3RlbmNlVmFsdWU+KGtleTogc3RyaW5nKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zdG9yYWdlW2tleV07XG4gICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyBudWxsIDogKHZhbHVlIGFzIFQpO1xuICB9XG5cbiAgYXN5bmMgX3JlbW92ZShrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGRlbGV0ZSB0aGlzLnN0b3JhZ2Vba2V5XTtcbiAgfVxuXG4gIF9hZGRMaXN0ZW5lcihfa2V5OiBzdHJpbmcsIF9saXN0ZW5lcjogU3RvcmFnZUV2ZW50TGlzdGVuZXIpOiB2b2lkIHtcbiAgICAvLyBMaXN0ZW5lcnMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIGluLW1lbW9yeSBzdG9yYWdlIHNpbmNlIGl0IGNhbm5vdCBiZSBzaGFyZWQgYWNyb3NzIHdpbmRvd3Mvd29ya2Vyc1xuICAgIHJldHVybjtcbiAgfVxuXG4gIF9yZW1vdmVMaXN0ZW5lcihfa2V5OiBzdHJpbmcsIF9saXN0ZW5lcjogU3RvcmFnZUV2ZW50TGlzdGVuZXIpOiB2b2lkIHtcbiAgICAvLyBMaXN0ZW5lcnMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIGluLW1lbW9yeSBzdG9yYWdlIHNpbmNlIGl0IGNhbm5vdCBiZSBzaGFyZWQgYWNyb3NzIHdpbmRvd3Mvd29ya2Vyc1xuICAgIHJldHVybjtcbiAgfVxufVxuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBQZXJzaXN0ZW5jZX0gb2YgdHlwZSAnTk9ORScuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgaW5NZW1vcnlQZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2UgPSBJbk1lbW9yeVBlcnNpc3RlbmNlO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGdldEFjY291bnRJbmZvIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IEFwaUtleSwgQXBwTmFtZSwgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IFBlcnNpc3RlZEJsb2IsIFBlcnNpc3RlbmNlSW50ZXJuYWwgfSBmcm9tICcuLi9wZXJzaXN0ZW5jZSc7XG5pbXBvcnQgeyBVc2VySW1wbCB9IGZyb20gJy4uL3VzZXIvdXNlcl9pbXBsJztcbmltcG9ydCB7IF9nZXRJbnN0YW5jZSB9IGZyb20gJy4uL3V0aWwvaW5zdGFudGlhdG9yJztcbmltcG9ydCB7IGluTWVtb3J5UGVyc2lzdGVuY2UgfSBmcm9tICcuL2luX21lbW9yeSc7XG5cbmV4cG9ydCBjb25zdCBlbnVtIEtleU5hbWUge1xuICBBVVRIX1VTRVIgPSAnYXV0aFVzZXInLFxuICBBVVRIX0VWRU5UID0gJ2F1dGhFdmVudCcsXG4gIFJFRElSRUNUX1VTRVIgPSAncmVkaXJlY3RVc2VyJyxcbiAgUEVSU0lTVEVOQ0VfVVNFUiA9ICdwZXJzaXN0ZW5jZSdcbn1cbmV4cG9ydCBjb25zdCBlbnVtIE5hbWVzcGFjZSB7XG4gIFBFUlNJU1RFTkNFID0gJ2ZpcmViYXNlJ1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3BlcnNpc3RlbmNlS2V5TmFtZShcbiAga2V5OiBzdHJpbmcsXG4gIGFwaUtleTogQXBpS2V5LFxuICBhcHBOYW1lOiBBcHBOYW1lXG4pOiBzdHJpbmcge1xuICByZXR1cm4gYCR7TmFtZXNwYWNlLlBFUlNJU1RFTkNFfToke2tleX06JHthcGlLZXl9OiR7YXBwTmFtZX1gO1xufVxuXG5leHBvcnQgY2xhc3MgUGVyc2lzdGVuY2VVc2VyTWFuYWdlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZnVsbFVzZXJLZXk6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBmdWxsUGVyc2lzdGVuY2VLZXk6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBib3VuZEV2ZW50SGFuZGxlcjogKCkgPT4gdm9pZDtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBwZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2VJbnRlcm5hbCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHVzZXJLZXk6IHN0cmluZ1xuICApIHtcbiAgICBjb25zdCB7IGNvbmZpZywgbmFtZSB9ID0gdGhpcy5hdXRoO1xuICAgIHRoaXMuZnVsbFVzZXJLZXkgPSBfcGVyc2lzdGVuY2VLZXlOYW1lKHRoaXMudXNlcktleSwgY29uZmlnLmFwaUtleSwgbmFtZSk7XG4gICAgdGhpcy5mdWxsUGVyc2lzdGVuY2VLZXkgPSBfcGVyc2lzdGVuY2VLZXlOYW1lKFxuICAgICAgS2V5TmFtZS5QRVJTSVNURU5DRV9VU0VSLFxuICAgICAgY29uZmlnLmFwaUtleSxcbiAgICAgIG5hbWVcbiAgICApO1xuICAgIHRoaXMuYm91bmRFdmVudEhhbmRsZXIgPSBhdXRoLl9vblN0b3JhZ2VFdmVudC5iaW5kKGF1dGgpO1xuICAgIHRoaXMucGVyc2lzdGVuY2UuX2FkZExpc3RlbmVyKHRoaXMuZnVsbFVzZXJLZXksIHRoaXMuYm91bmRFdmVudEhhbmRsZXIpO1xuICB9XG5cbiAgc2V0Q3VycmVudFVzZXIodXNlcjogVXNlckludGVybmFsKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMucGVyc2lzdGVuY2UuX3NldCh0aGlzLmZ1bGxVc2VyS2V5LCB1c2VyLnRvSlNPTigpKTtcbiAgfVxuXG4gIGFzeW5jIGdldEN1cnJlbnRVc2VyKCk6IFByb21pc2U8VXNlckludGVybmFsIHwgbnVsbD4ge1xuICAgIGNvbnN0IGJsb2IgPSBhd2FpdCB0aGlzLnBlcnNpc3RlbmNlLl9nZXQ8UGVyc2lzdGVkQmxvYiB8IHN0cmluZz4oXG4gICAgICB0aGlzLmZ1bGxVc2VyS2V5XG4gICAgKTtcbiAgICBpZiAoIWJsb2IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJsb2IgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldEFjY291bnRJbmZvKHRoaXMuYXV0aCwgeyBpZFRva2VuOiBibG9iIH0pLmNhdGNoKFxuICAgICAgICAoKSA9PiB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFVzZXJJbXBsLl9mcm9tR2V0QWNjb3VudEluZm9SZXNwb25zZSh0aGlzLmF1dGgsIHJlc3BvbnNlLCBibG9iKTtcbiAgICB9XG4gICAgcmV0dXJuIFVzZXJJbXBsLl9mcm9tSlNPTih0aGlzLmF1dGgsIGJsb2IpO1xuICB9XG5cbiAgcmVtb3ZlQ3VycmVudFVzZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMucGVyc2lzdGVuY2UuX3JlbW92ZSh0aGlzLmZ1bGxVc2VyS2V5KTtcbiAgfVxuXG4gIHNhdmVQZXJzaXN0ZW5jZUZvclJlZGlyZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnBlcnNpc3RlbmNlLl9zZXQoXG4gICAgICB0aGlzLmZ1bGxQZXJzaXN0ZW5jZUtleSxcbiAgICAgIHRoaXMucGVyc2lzdGVuY2UudHlwZVxuICAgICk7XG4gIH1cblxuICBhc3luYyBzZXRQZXJzaXN0ZW5jZShuZXdQZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2VJbnRlcm5hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnBlcnNpc3RlbmNlID09PSBuZXdQZXJzaXN0ZW5jZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRVc2VyID0gYXdhaXQgdGhpcy5nZXRDdXJyZW50VXNlcigpO1xuICAgIGF3YWl0IHRoaXMucmVtb3ZlQ3VycmVudFVzZXIoKTtcblxuICAgIHRoaXMucGVyc2lzdGVuY2UgPSBuZXdQZXJzaXN0ZW5jZTtcblxuICAgIGlmIChjdXJyZW50VXNlcikge1xuICAgICAgcmV0dXJuIHRoaXMuc2V0Q3VycmVudFVzZXIoY3VycmVudFVzZXIpO1xuICAgIH1cbiAgfVxuXG4gIGRlbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnBlcnNpc3RlbmNlLl9yZW1vdmVMaXN0ZW5lcih0aGlzLmZ1bGxVc2VyS2V5LCB0aGlzLmJvdW5kRXZlbnRIYW5kbGVyKTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjcmVhdGUoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5OiBQZXJzaXN0ZW5jZUludGVybmFsW10sXG4gICAgdXNlcktleSA9IEtleU5hbWUuQVVUSF9VU0VSXG4gICk6IFByb21pc2U8UGVyc2lzdGVuY2VVc2VyTWFuYWdlcj4ge1xuICAgIGlmICghcGVyc2lzdGVuY2VIaWVyYXJjaHkubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gbmV3IFBlcnNpc3RlbmNlVXNlck1hbmFnZXIoXG4gICAgICAgIF9nZXRJbnN0YW5jZShpbk1lbW9yeVBlcnNpc3RlbmNlKSxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgdXNlcktleVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBFbGltaW5hdGUgYW55IHBlcnNpc3RlbmNlcyB0aGF0IGFyZSBub3QgYXZhaWxhYmxlXG4gICAgY29uc3QgYXZhaWxhYmxlUGVyc2lzdGVuY2VzID0gKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5Lm1hcChhc3luYyBwZXJzaXN0ZW5jZSA9PiB7XG4gICAgICAgICAgaWYgKGF3YWl0IHBlcnNpc3RlbmNlLl9pc0F2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gcGVyc2lzdGVuY2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgKS5maWx0ZXIocGVyc2lzdGVuY2UgPT4gcGVyc2lzdGVuY2UpIGFzIFBlcnNpc3RlbmNlSW50ZXJuYWxbXTtcblxuICAgIC8vIEZhbGwgYmFjayB0byB0aGUgZmlyc3QgcGVyc2lzdGVuY2UgbGlzdGVkLCBvciBpbiBtZW1vcnkgaWYgbm9uZSBhdmFpbGFibGVcbiAgICBsZXQgc2VsZWN0ZWRQZXJzaXN0ZW5jZSA9XG4gICAgICBhdmFpbGFibGVQZXJzaXN0ZW5jZXNbMF0gfHxcbiAgICAgIF9nZXRJbnN0YW5jZTxQZXJzaXN0ZW5jZUludGVybmFsPihpbk1lbW9yeVBlcnNpc3RlbmNlKTtcblxuICAgIGNvbnN0IGtleSA9IF9wZXJzaXN0ZW5jZUtleU5hbWUodXNlcktleSwgYXV0aC5jb25maWcuYXBpS2V5LCBhdXRoLm5hbWUpO1xuXG4gICAgLy8gUHVsbCBvdXQgdGhlIGV4aXN0aW5nIHVzZXIsIHNldHRpbmcgdGhlIGNob3NlbiBwZXJzaXN0ZW5jZSB0byB0aGF0XG4gICAgLy8gcGVyc2lzdGVuY2UgaWYgdGhlIHVzZXIgZXhpc3RzLlxuICAgIGxldCB1c2VyVG9NaWdyYXRlOiBVc2VySW50ZXJuYWwgfCBudWxsID0gbnVsbDtcbiAgICAvLyBOb3RlLCBoZXJlIHdlIGNoZWNrIGZvciBhIHVzZXIgaW4gX2FsbF8gcGVyc2lzdGVuY2VzLCBub3QganVzdCB0aGVcbiAgICAvLyBvbmVzIGRlZW1lZCBhdmFpbGFibGUuIElmIHdlIGNhbiBtaWdyYXRlIGEgdXNlciBvdXQgb2YgYSBicm9rZW5cbiAgICAvLyBwZXJzaXN0ZW5jZSwgd2Ugd2lsbCAoYnV0IG9ubHkgaWYgdGhhdCBwZXJzaXN0ZW5jZSBzdXBwb3J0cyBtaWdyYXRpb24pLlxuICAgIGZvciAoY29uc3QgcGVyc2lzdGVuY2Ugb2YgcGVyc2lzdGVuY2VIaWVyYXJjaHkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJsb2IgPSBhd2FpdCBwZXJzaXN0ZW5jZS5fZ2V0PFBlcnNpc3RlZEJsb2IgfCBzdHJpbmc+KGtleSk7XG4gICAgICAgIGlmIChibG9iKSB7XG4gICAgICAgICAgbGV0IHVzZXI6IFVzZXJJbnRlcm5hbDtcbiAgICAgICAgICBpZiAodHlwZW9mIGJsb2IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldEFjY291bnRJbmZvKGF1dGgsIHtcbiAgICAgICAgICAgICAgaWRUb2tlbjogYmxvYlxuICAgICAgICAgICAgfSkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB1c2VyID0gYXdhaXQgVXNlckltcGwuX2Zyb21HZXRBY2NvdW50SW5mb1Jlc3BvbnNlKFxuICAgICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgICByZXNwb25zZSxcbiAgICAgICAgICAgICAgYmxvYlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXNlciA9IFVzZXJJbXBsLl9mcm9tSlNPTihhdXRoLCBibG9iKTsgLy8gdGhyb3dzIGZvciB1bnBhcnNhYmxlIGJsb2IgKHdyb25nIGZvcm1hdClcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHBlcnNpc3RlbmNlICE9PSBzZWxlY3RlZFBlcnNpc3RlbmNlKSB7XG4gICAgICAgICAgICB1c2VyVG9NaWdyYXRlID0gdXNlcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2VsZWN0ZWRQZXJzaXN0ZW5jZSA9IHBlcnNpc3RlbmNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHt9XG4gICAgfVxuXG4gICAgLy8gSWYgd2UgZmluZCB0aGUgdXNlciBpbiBhIHBlcnNpc3RlbmNlIHRoYXQgZG9lcyBzdXBwb3J0IG1pZ3JhdGlvbiwgdXNlXG4gICAgLy8gdGhhdCBtaWdyYXRpb24gcGF0aCAob2Ygb25seSBwZXJzaXN0ZW5jZXMgdGhhdCBzdXBwb3J0IG1pZ3JhdGlvbilcbiAgICBjb25zdCBtaWdyYXRpb25IaWVyYXJjaHkgPSBhdmFpbGFibGVQZXJzaXN0ZW5jZXMuZmlsdGVyKFxuICAgICAgcCA9PiBwLl9zaG91bGRBbGxvd01pZ3JhdGlvblxuICAgICk7XG5cbiAgICAvLyBJZiB0aGUgcGVyc2lzdGVuY2UgZG9lcyBfbm90XyBhbGxvdyBtaWdyYXRpb24sIGp1c3QgZmluaXNoIG9mZiBoZXJlXG4gICAgaWYgKFxuICAgICAgIXNlbGVjdGVkUGVyc2lzdGVuY2UuX3Nob3VsZEFsbG93TWlncmF0aW9uIHx8XG4gICAgICAhbWlncmF0aW9uSGllcmFyY2h5Lmxlbmd0aFxuICAgICkge1xuICAgICAgcmV0dXJuIG5ldyBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyKHNlbGVjdGVkUGVyc2lzdGVuY2UsIGF1dGgsIHVzZXJLZXkpO1xuICAgIH1cblxuICAgIHNlbGVjdGVkUGVyc2lzdGVuY2UgPSBtaWdyYXRpb25IaWVyYXJjaHlbMF07XG4gICAgaWYgKHVzZXJUb01pZ3JhdGUpIHtcbiAgICAgIC8vIFRoaXMgbm9ybWFsbHkgc2hvdWxkbid0IHRocm93IHNpbmNlIGNob3NlblBlcnNpc3RlbmNlLmlzQXZhaWxhYmxlKCkgaXMgdHJ1ZSwgYnV0IGlmIGl0IGRvZXNcbiAgICAgIC8vIHdlJ2xsIGp1c3QgbGV0IGl0IGJ1YmJsZSB0byBzdXJmYWNlIHRoZSBlcnJvci5cbiAgICAgIGF3YWl0IHNlbGVjdGVkUGVyc2lzdGVuY2UuX3NldChrZXksIHVzZXJUb01pZ3JhdGUudG9KU09OKCkpO1xuICAgIH1cblxuICAgIC8vIEF0dGVtcHQgdG8gY2xlYXIgdGhlIGtleSBpbiBvdGhlciBwZXJzaXN0ZW5jZXMgYnV0IGlnbm9yZSBlcnJvcnMuIFRoaXMgaGVscHMgcHJldmVudCBpc3N1ZXNcbiAgICAvLyBzdWNoIGFzIHVzZXJzIGdldHRpbmcgc3R1Y2sgd2l0aCBhIHByZXZpb3VzIGFjY291bnQgYWZ0ZXIgc2lnbmluZyBvdXQgYW5kIHJlZnJlc2hpbmcgdGhlIHRhYi5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5Lm1hcChhc3luYyBwZXJzaXN0ZW5jZSA9PiB7XG4gICAgICAgIGlmIChwZXJzaXN0ZW5jZSAhPT0gc2VsZWN0ZWRQZXJzaXN0ZW5jZSkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBwZXJzaXN0ZW5jZS5fcmVtb3ZlKGtleSk7XG4gICAgICAgICAgfSBjYXRjaCB7fVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIG5ldyBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyKHNlbGVjdGVkUGVyc2lzdGVuY2UsIGF1dGgsIHVzZXJLZXkpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgaXNJRSwgZ2V0VUEgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmludGVyZmFjZSBOYXZpZ2F0b3JTdGFuZGFsb25lIGV4dGVuZHMgTmF2aWdhdG9yIHtcbiAgc3RhbmRhbG9uZT86IHVua25vd247XG59XG5cbmludGVyZmFjZSBEb2N1bWVudCB7XG4gIGRvY3VtZW50TW9kZT86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBFbnVtcyBmb3IgQnJvd3NlciBuYW1lLlxuICovXG5leHBvcnQgY29uc3QgZW51bSBCcm93c2VyTmFtZSB7XG4gIEFORFJPSUQgPSAnQW5kcm9pZCcsXG4gIEJMQUNLQkVSUlkgPSAnQmxhY2tiZXJyeScsXG4gIEVER0UgPSAnRWRnZScsXG4gIEZJUkVGT1ggPSAnRmlyZWZveCcsXG4gIElFID0gJ0lFJyxcbiAgSUVNT0JJTEUgPSAnSUVNb2JpbGUnLFxuICBPUEVSQSA9ICdPcGVyYScsXG4gIE9USEVSID0gJ090aGVyJyxcbiAgQ0hST01FID0gJ0Nocm9tZScsXG4gIFNBRkFSSSA9ICdTYWZhcmknLFxuICBTSUxLID0gJ1NpbGsnLFxuICBXRUJPUyA9ICdXZWJvcydcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgdGhlIGJyb3dzZXIgZm9yIHRoZSBwdXJwb3NlcyBvZiByZXBvcnRpbmcgdXNhZ2UgdG8gdGhlIEFQSVxuICovXG5leHBvcnQgZnVuY3Rpb24gX2dldEJyb3dzZXJOYW1lKHVzZXJBZ2VudDogc3RyaW5nKTogQnJvd3Nlck5hbWUgfCBzdHJpbmcge1xuICBjb25zdCB1YSA9IHVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpO1xuICBpZiAodWEuaW5jbHVkZXMoJ29wZXJhLycpIHx8IHVhLmluY2x1ZGVzKCdvcHIvJykgfHwgdWEuaW5jbHVkZXMoJ29waW9zLycpKSB7XG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLk9QRVJBO1xuICB9IGVsc2UgaWYgKF9pc0lFTW9iaWxlKHVhKSkge1xuICAgIC8vIFdpbmRvd3MgcGhvbmUgSUVNb2JpbGUgYnJvd3Nlci5cbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuSUVNT0JJTEU7XG4gIH0gZWxzZSBpZiAodWEuaW5jbHVkZXMoJ21zaWUnKSB8fCB1YS5pbmNsdWRlcygndHJpZGVudC8nKSkge1xuICAgIHJldHVybiBCcm93c2VyTmFtZS5JRTtcbiAgfSBlbHNlIGlmICh1YS5pbmNsdWRlcygnZWRnZS8nKSkge1xuICAgIHJldHVybiBCcm93c2VyTmFtZS5FREdFO1xuICB9IGVsc2UgaWYgKF9pc0ZpcmVmb3godWEpKSB7XG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLkZJUkVGT1g7XG4gIH0gZWxzZSBpZiAodWEuaW5jbHVkZXMoJ3NpbGsvJykpIHtcbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuU0lMSztcbiAgfSBlbHNlIGlmIChfaXNCbGFja0JlcnJ5KHVhKSkge1xuICAgIC8vIEJsYWNrYmVycnkgYnJvd3Nlci5cbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuQkxBQ0tCRVJSWTtcbiAgfSBlbHNlIGlmIChfaXNXZWJPUyh1YSkpIHtcbiAgICAvLyBXZWJPUyBkZWZhdWx0IGJyb3dzZXIuXG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLldFQk9TO1xuICB9IGVsc2UgaWYgKF9pc1NhZmFyaSh1YSkpIHtcbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuU0FGQVJJO1xuICB9IGVsc2UgaWYgKFxuICAgICh1YS5pbmNsdWRlcygnY2hyb21lLycpIHx8IF9pc0Nocm9tZUlPUyh1YSkpICYmXG4gICAgIXVhLmluY2x1ZGVzKCdlZGdlLycpXG4gICkge1xuICAgIHJldHVybiBCcm93c2VyTmFtZS5DSFJPTUU7XG4gIH0gZWxzZSBpZiAoX2lzQW5kcm9pZCh1YSkpIHtcbiAgICAvLyBBbmRyb2lkIHN0b2NrIGJyb3dzZXIuXG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLkFORFJPSUQ7XG4gIH0gZWxzZSB7XG4gICAgLy8gTW9zdCBtb2Rlcm4gYnJvd3NlcnMgaGF2ZSBuYW1lL3ZlcnNpb24gYXQgZW5kIG9mIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgIGNvbnN0IHJlID0gLyhbYS16QS1aXFxkXFwuXSspXFwvW2EtekEtWlxcZFxcLl0qJC87XG4gICAgY29uc3QgbWF0Y2hlcyA9IHVzZXJBZ2VudC5tYXRjaChyZSk7XG4gICAgaWYgKG1hdGNoZXM/Lmxlbmd0aCA9PT0gMikge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbMV07XG4gICAgfVxuICB9XG4gIHJldHVybiBCcm93c2VyTmFtZS5PVEhFUjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0ZpcmVmb3godWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAvZmlyZWZveFxcLy9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzU2FmYXJpKHVzZXJBZ2VudCA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgY29uc3QgdWEgPSB1c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChcbiAgICB1YS5pbmNsdWRlcygnc2FmYXJpLycpICYmXG4gICAgIXVhLmluY2x1ZGVzKCdjaHJvbWUvJykgJiZcbiAgICAhdWEuaW5jbHVkZXMoJ2NyaW9zLycpICYmXG4gICAgIXVhLmluY2x1ZGVzKCdhbmRyb2lkJylcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0Nocm9tZUlPUyh1YSA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9jcmlvc1xcLy9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSUVNb2JpbGUodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAvaWVtb2JpbGUvaS50ZXN0KHVhKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0FuZHJvaWQodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAvYW5kcm9pZC9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzQmxhY2tCZXJyeSh1YSA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9ibGFja2JlcnJ5L2kudGVzdCh1YSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfaXNXZWJPUyh1YSA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgcmV0dXJuIC93ZWJvcy9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSU9TKHVhID0gZ2V0VUEoKSk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIC9pcGhvbmV8aXBhZHxpcG9kL2kudGVzdCh1YSkgfHxcbiAgICAoL21hY2ludG9zaC9pLnRlc3QodWEpICYmIC9tb2JpbGUvaS50ZXN0KHVhKSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0lPUzdPcjgodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgLyhpUGFkfGlQaG9uZXxpUG9kKS4qT1MgN19cXGQvaS50ZXN0KHVhKSB8fFxuICAgIC8oaVBhZHxpUGhvbmV8aVBvZCkuKk9TIDhfXFxkL2kudGVzdCh1YSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0lPU1N0YW5kYWxvbmUodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiBfaXNJT1ModWEpICYmICEhKHdpbmRvdy5uYXZpZ2F0b3IgYXMgTmF2aWdhdG9yU3RhbmRhbG9uZSk/LnN0YW5kYWxvbmU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfaXNJRTEwKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNJRSgpICYmIChkb2N1bWVudCBhcyBEb2N1bWVudCkuZG9jdW1lbnRNb2RlID09PSAxMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc01vYmlsZUJyb3dzZXIodWE6IHN0cmluZyA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgLy8gVE9ETzogaW1wbGVtZW50IGdldEJyb3dzZXJOYW1lIGVxdWl2YWxlbnQgZm9yIE9TLlxuICByZXR1cm4gKFxuICAgIF9pc0lPUyh1YSkgfHxcbiAgICBfaXNBbmRyb2lkKHVhKSB8fFxuICAgIF9pc1dlYk9TKHVhKSB8fFxuICAgIF9pc0JsYWNrQmVycnkodWEpIHx8XG4gICAgL3dpbmRvd3MgcGhvbmUvaS50ZXN0KHVhKSB8fFxuICAgIF9pc0lFTW9iaWxlKHVhKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSWZyYW1lKCk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIC8vIENoZWNrIHRoYXQgdGhlIGN1cnJlbnQgd2luZG93IGlzIG5vdCB0aGUgdG9wIHdpbmRvdy5cbiAgICAvLyBJZiBzbywgcmV0dXJuIHRydWUuXG4gICAgcmV0dXJuICEhKHdpbmRvdyAmJiB3aW5kb3cgIT09IHdpbmRvdy50b3ApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgU0RLX1ZFUlNJT04gfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IF9nZXRCcm93c2VyTmFtZSB9IGZyb20gJy4vYnJvd3Nlcic7XG5pbXBvcnQgeyBnZXRVQSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IGNvbnN0IGVudW0gQ2xpZW50SW1wbGVtZW50YXRpb24ge1xuICBDT1JFID0gJ0pzQ29yZSdcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IGVudW0gQ2xpZW50UGxhdGZvcm0ge1xuICBCUk9XU0VSID0gJ0Jyb3dzZXInLFxuICBOT0RFID0gJ05vZGUnLFxuICBSRUFDVF9OQVRJVkUgPSAnUmVhY3ROYXRpdmUnLFxuICBDT1JET1ZBID0gJ0NvcmRvdmEnLFxuICBXT1JLRVIgPSAnV29ya2VyJyxcbiAgV0VCX0VYVEVOU0lPTiA9ICdXZWJFeHRlbnNpb24nXG59XG5cbi8qXG4gKiBEZXRlcm1pbmUgdGhlIFNESyB2ZXJzaW9uIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gX2dldENsaWVudFZlcnNpb24oXG4gIGNsaWVudFBsYXRmb3JtOiBDbGllbnRQbGF0Zm9ybSxcbiAgZnJhbWV3b3JrczogcmVhZG9ubHkgc3RyaW5nW10gPSBbXVxuKTogc3RyaW5nIHtcbiAgbGV0IHJlcG9ydGVkUGxhdGZvcm06IHN0cmluZztcbiAgc3dpdGNoIChjbGllbnRQbGF0Zm9ybSkge1xuICAgIGNhc2UgQ2xpZW50UGxhdGZvcm0uQlJPV1NFUjpcbiAgICAgIC8vIEluIGEgYnJvd3NlciBlbnZpcm9ubWVudCwgcmVwb3J0IHRoZSBicm93c2VyIG5hbWUuXG4gICAgICByZXBvcnRlZFBsYXRmb3JtID0gX2dldEJyb3dzZXJOYW1lKGdldFVBKCkpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBDbGllbnRQbGF0Zm9ybS5XT1JLRVI6XG4gICAgICAvLyBUZWNobmljYWxseSBhIHdvcmtlciBydW5zIGZyb20gYSBicm93c2VyIGJ1dCB3ZSBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYVxuICAgICAgLy8gd29ya2VyIGZyb20gYSBicm93c2VyLlxuICAgICAgLy8gRm9yIGV4YW1wbGU6IENocm9tZS1Xb3JrZXIvSnNDb3JlLzQuOS4xL0ZpcmViYXNlQ29yZS13ZWIuXG4gICAgICByZXBvcnRlZFBsYXRmb3JtID0gYCR7X2dldEJyb3dzZXJOYW1lKGdldFVBKCkpfS0ke2NsaWVudFBsYXRmb3JtfWA7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgcmVwb3J0ZWRQbGF0Zm9ybSA9IGNsaWVudFBsYXRmb3JtO1xuICB9XG4gIGNvbnN0IHJlcG9ydGVkRnJhbWV3b3JrcyA9IGZyYW1ld29ya3MubGVuZ3RoXG4gICAgPyBmcmFtZXdvcmtzLmpvaW4oJywnKVxuICAgIDogJ0ZpcmViYXNlQ29yZS13ZWInOyAvKiBkZWZhdWx0IHZhbHVlIGlmIG5vIG90aGVyIGZyYW1ld29yayBpcyB1c2VkICovXG4gIHJldHVybiBgJHtyZXBvcnRlZFBsYXRmb3JtfS8ke0NsaWVudEltcGxlbWVudGF0aW9uLkNPUkV9LyR7U0RLX1ZFUlNJT059LyR7cmVwb3J0ZWRGcmFtZXdvcmtzfWA7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBVbnN1YnNjcmliZSwgVXNlciB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuaW50ZXJmYWNlIE1pZGRsZXdhcmVFbnRyeSB7XG4gICh1c2VyOiBVc2VyIHwgbnVsbCk6IFByb21pc2U8dm9pZD47XG4gIG9uQWJvcnQ/OiAoKSA9PiB2b2lkO1xufVxuXG5leHBvcnQgY2xhc3MgQXV0aE1pZGRsZXdhcmVRdWV1ZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcXVldWU6IE1pZGRsZXdhcmVFbnRyeVtdID0gW107XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBhdXRoOiBBdXRoSW50ZXJuYWwpIHt9XG5cbiAgcHVzaENhbGxiYWNrKFxuICAgIGNhbGxiYWNrOiAodXNlcjogVXNlciB8IG51bGwpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICAgIG9uQWJvcnQ/OiAoKSA9PiB2b2lkXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICAvLyBUaGUgY2FsbGJhY2sgY291bGQgYmUgc3luYyBvciBhc3luYy4gV3JhcCBpdCBpbnRvIGFcbiAgICAvLyBmdW5jdGlvbiB0aGF0IGlzIGFsd2F5cyBhc3luYy5cbiAgICBjb25zdCB3cmFwcGVkQ2FsbGJhY2s6IE1pZGRsZXdhcmVFbnRyeSA9IChcbiAgICAgIHVzZXI6IFVzZXIgfCBudWxsXG4gICAgKTogUHJvbWlzZTx2b2lkPiA9PlxuICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGNhbGxiYWNrKHVzZXIpO1xuICAgICAgICAgIC8vIEVpdGhlciByZXNvbHZlIHdpdGggZXhpc3RpbmcgcHJvbWlzZSBvciB3cmFwIGEgbm9uLXByb21pc2VcbiAgICAgICAgICAvLyByZXR1cm4gdmFsdWUgaW50byBhIHByb21pc2UuXG4gICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gU3luYyBjYWxsYmFjayB0aHJvd3MuXG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAvLyBBdHRhY2ggdGhlIG9uQWJvcnQgaWYgcHJlc2VudFxuICAgIHdyYXBwZWRDYWxsYmFjay5vbkFib3J0ID0gb25BYm9ydDtcbiAgICB0aGlzLnF1ZXVlLnB1c2god3JhcHBlZENhbGxiYWNrKTtcblxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5xdWV1ZS5sZW5ndGggLSAxO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAvLyBVbnN1YnNjcmliZS4gUmVwbGFjZSB3aXRoIG5vLW9wLiBEbyBub3QgcmVtb3ZlIGZyb20gYXJyYXksIG9yIGl0IHdpbGwgZGlzdHVyYlxuICAgICAgLy8gaW5kZXhpbmcgb2Ygb3RoZXIgZWxlbWVudHMuXG4gICAgICB0aGlzLnF1ZXVlW2luZGV4XSA9ICgpID0+IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG4gIH1cblxuICBhc3luYyBydW5NaWRkbGV3YXJlKG5leHRVc2VyOiBVc2VyIHwgbnVsbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmF1dGguY3VycmVudFVzZXIgPT09IG5leHRVc2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gV2hpbGUgcnVubmluZyB0aGUgbWlkZGxld2FyZSwgYnVpbGQgYSB0ZW1wb3Jhcnkgc3RhY2sgb2Ygb25BYm9ydFxuICAgIC8vIGNhbGxiYWNrcyB0byBjYWxsIGlmIG9uZSBtaWRkbGV3YXJlIGNhbGxiYWNrIHJlamVjdHMuXG5cbiAgICBjb25zdCBvbkFib3J0U3RhY2s6IEFycmF5PCgpID0+IHZvaWQ+ID0gW107XG4gICAgdHJ5IHtcbiAgICAgIGZvciAoY29uc3QgYmVmb3JlU3RhdGVDYWxsYmFjayBvZiB0aGlzLnF1ZXVlKSB7XG4gICAgICAgIGF3YWl0IGJlZm9yZVN0YXRlQ2FsbGJhY2sobmV4dFVzZXIpO1xuXG4gICAgICAgIC8vIE9ubHkgcHVzaCB0aGUgb25BYm9ydCBpZiB0aGUgY2FsbGJhY2sgc3VjY2VlZHNcbiAgICAgICAgaWYgKGJlZm9yZVN0YXRlQ2FsbGJhY2sub25BYm9ydCkge1xuICAgICAgICAgIG9uQWJvcnRTdGFjay5wdXNoKGJlZm9yZVN0YXRlQ2FsbGJhY2sub25BYm9ydCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBSdW4gYWxsIG9uQWJvcnQsIHdpdGggc2VwYXJhdGUgdHJ5L2NhdGNoIHRvIGlnbm9yZSBhbnkgZXJyb3JzIGFuZFxuICAgICAgLy8gY29udGludWVcbiAgICAgIG9uQWJvcnRTdGFjay5yZXZlcnNlKCk7XG4gICAgICBmb3IgKGNvbnN0IG9uQWJvcnQgb2Ygb25BYm9ydFN0YWNrKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgb25BYm9ydCgpO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgLyogc3dhbGxvdyBlcnJvciAqL1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IHRoaXMuYXV0aC5fZXJyb3JGYWN0b3J5LmNyZWF0ZShBdXRoRXJyb3JDb2RlLkxPR0lOX0JMT0NLRUQsIHtcbiAgICAgICAgb3JpZ2luYWxNZXNzYWdlOiAoZSBhcyBFcnJvcik/Lm1lc3NhZ2VcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeVxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuLyoqXG4gKiBSZXF1ZXN0IG9iamVjdCBmb3IgZmV0Y2hpbmcgdGhlIHBhc3N3b3JkIHBvbGljeS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRQYXNzd29yZFBvbGljeVJlcXVlc3Qge1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXNwb25zZSBvYmplY3QgZm9yIGZldGNoaW5nIHRoZSBwYXNzd29yZCBwb2xpY3kuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UGFzc3dvcmRQb2xpY3lSZXNwb25zZSB7XG4gIGN1c3RvbVN0cmVuZ3RoT3B0aW9uczoge1xuICAgIG1pblBhc3N3b3JkTGVuZ3RoPzogbnVtYmVyO1xuICAgIG1heFBhc3N3b3JkTGVuZ3RoPzogbnVtYmVyO1xuICAgIGNvbnRhaW5zTG93ZXJjYXNlQ2hhcmFjdGVyPzogYm9vbGVhbjtcbiAgICBjb250YWluc1VwcGVyY2FzZUNoYXJhY3Rlcj86IGJvb2xlYW47XG4gICAgY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyPzogYm9vbGVhbjtcbiAgICBjb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3Rlcj86IGJvb2xlYW47XG4gIH07XG4gIGFsbG93ZWROb25BbHBoYW51bWVyaWNDaGFyYWN0ZXJzPzogc3RyaW5nW107XG4gIGVuZm9yY2VtZW50U3RhdGU6IHN0cmluZztcbiAgZm9yY2VVcGdyYWRlT25TaWduaW4/OiBib29sZWFuO1xuICBzY2hlbWFWZXJzaW9uOiBudW1iZXI7XG59XG5cbi8qKlxuICogRmV0Y2hlcyB0aGUgcGFzc3dvcmQgcG9saWN5IGZvciB0aGUgY3VycmVudGx5IHNldCB0ZW5hbnQgb3IgdGhlIHByb2plY3QgaWYgbm8gdGVuYW50IGlzIHNldC5cbiAqXG4gKiBAcGFyYW0gYXV0aCBBdXRoIG9iamVjdC5cbiAqIEBwYXJhbSByZXF1ZXN0IFBhc3N3b3JkIHBvbGljeSByZXF1ZXN0LlxuICogQHJldHVybnMgUGFzc3dvcmQgcG9saWN5IHJlc3BvbnNlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX2dldFBhc3N3b3JkUG9saWN5KFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBHZXRQYXNzd29yZFBvbGljeVJlcXVlc3QgPSB7fVxuKTogUHJvbWlzZTxHZXRQYXNzd29yZFBvbGljeVJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgR2V0UGFzc3dvcmRQb2xpY3lSZXF1ZXN0LFxuICAgIEdldFBhc3N3b3JkUG9saWN5UmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuR0VULFxuICAgIEVuZHBvaW50LkdFVF9QQVNTV09SRF9QT0xJQ1ksXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgR2V0UGFzc3dvcmRQb2xpY3lSZXNwb25zZSB9IGZyb20gJy4uLy4uL2FwaS9wYXNzd29yZF9wb2xpY3kvZ2V0X3Bhc3N3b3JkX3BvbGljeSc7XG5pbXBvcnQge1xuICBQYXNzd29yZFBvbGljeUN1c3RvbVN0cmVuZ3RoT3B0aW9ucyxcbiAgUGFzc3dvcmRQb2xpY3lJbnRlcm5hbCxcbiAgUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWxcbn0gZnJvbSAnLi4vLi4vbW9kZWwvcGFzc3dvcmRfcG9saWN5JztcbmltcG9ydCB7IFBhc3N3b3JkVmFsaWRhdGlvblN0YXR1cyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbi8vIE1pbmltdW0gbWluIHBhc3N3b3JkIGxlbmd0aCBlbmZvcmNlZCBieSB0aGUgYmFja2VuZCwgZXZlbiBpZiBubyBtaW5pbXVtIGxlbmd0aCBpcyBzZXQuXG5jb25zdCBNSU5JTVVNX01JTl9QQVNTV09SRF9MRU5HVEggPSA2O1xuXG4vKipcbiAqIFN0b3JlcyBwYXNzd29yZCBwb2xpY3kgcmVxdWlyZW1lbnRzIGFuZCBwcm92aWRlcyBwYXNzd29yZCB2YWxpZGF0aW9uIGFnYWluc3QgdGhlIHBvbGljeS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIFBhc3N3b3JkUG9saWN5SW1wbCBpbXBsZW1lbnRzIFBhc3N3b3JkUG9saWN5SW50ZXJuYWwge1xuICByZWFkb25seSBjdXN0b21TdHJlbmd0aE9wdGlvbnM6IFBhc3N3b3JkUG9saWN5Q3VzdG9tU3RyZW5ndGhPcHRpb25zO1xuICByZWFkb25seSBhbGxvd2VkTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyczogc3RyaW5nO1xuICByZWFkb25seSBlbmZvcmNlbWVudFN0YXRlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZvcmNlVXBncmFkZU9uU2lnbmluOiBib29sZWFuO1xuICByZWFkb25seSBzY2hlbWFWZXJzaW9uOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IocmVzcG9uc2U6IEdldFBhc3N3b3JkUG9saWN5UmVzcG9uc2UpIHtcbiAgICAvLyBPbmx5IGluY2x1ZGUgY3VzdG9tIHN0cmVuZ3RoIG9wdGlvbnMgZGVmaW5lZCBpbiB0aGUgcmVzcG9uc2UuXG4gICAgY29uc3QgcmVzcG9uc2VPcHRpb25zID0gcmVzcG9uc2UuY3VzdG9tU3RyZW5ndGhPcHRpb25zO1xuICAgIHRoaXMuY3VzdG9tU3RyZW5ndGhPcHRpb25zID0ge307XG4gICAgLy8gVE9ETzogUmVtb3ZlIG9uY2UgdGhlIGJhY2tlbmQgaXMgdXBkYXRlZCB0byBpbmNsdWRlIHRoZSBtaW5pbXVtIG1pbiBwYXNzd29yZCBsZW5ndGggaW5zdGVhZCBvZiB1bmRlZmluZWQgd2hlbiB0aGVyZSBpcyBubyBtaW5pbXVtIGxlbmd0aCBzZXQuXG4gICAgdGhpcy5jdXN0b21TdHJlbmd0aE9wdGlvbnMubWluUGFzc3dvcmRMZW5ndGggPVxuICAgICAgcmVzcG9uc2VPcHRpb25zLm1pblBhc3N3b3JkTGVuZ3RoID8/IE1JTklNVU1fTUlOX1BBU1NXT1JEX0xFTkdUSDtcbiAgICBpZiAocmVzcG9uc2VPcHRpb25zLm1heFBhc3N3b3JkTGVuZ3RoKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5tYXhQYXNzd29yZExlbmd0aCA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5tYXhQYXNzd29yZExlbmd0aDtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUNoYXJhY3RlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUxldHRlciA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUNoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc1VwcGVyY2FzZUNoYXJhY3RlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc1VwcGVyY2FzZUxldHRlciA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5jb250YWluc1VwcGVyY2FzZUNoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc051bWVyaWNDaGFyYWN0ZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5jdXN0b21TdHJlbmd0aE9wdGlvbnMuY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyID1cbiAgICAgICAgcmVzcG9uc2VPcHRpb25zLmNvbnRhaW5zTnVtZXJpY0NoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlciA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlcjtcbiAgICB9XG5cbiAgICB0aGlzLmVuZm9yY2VtZW50U3RhdGUgPSByZXNwb25zZS5lbmZvcmNlbWVudFN0YXRlO1xuICAgIGlmICh0aGlzLmVuZm9yY2VtZW50U3RhdGUgPT09ICdFTkZPUkNFTUVOVF9TVEFURV9VTlNQRUNJRklFRCcpIHtcbiAgICAgIHRoaXMuZW5mb3JjZW1lbnRTdGF0ZSA9ICdPRkYnO1xuICAgIH1cblxuICAgIC8vIFVzZSBhbiBlbXB0eSBzdHJpbmcgaWYgbm8gbm9uLWFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzIGFyZSBzcGVjaWZpZWQgaW4gdGhlIHJlc3BvbnNlLlxuICAgIHRoaXMuYWxsb3dlZE5vbkFscGhhbnVtZXJpY0NoYXJhY3RlcnMgPVxuICAgICAgcmVzcG9uc2UuYWxsb3dlZE5vbkFscGhhbnVtZXJpY0NoYXJhY3RlcnM/LmpvaW4oJycpID8/ICcnO1xuXG4gICAgdGhpcy5mb3JjZVVwZ3JhZGVPblNpZ25pbiA9IHJlc3BvbnNlLmZvcmNlVXBncmFkZU9uU2lnbmluID8/IGZhbHNlO1xuICAgIHRoaXMuc2NoZW1hVmVyc2lvbiA9IHJlc3BvbnNlLnNjaGVtYVZlcnNpb247XG4gIH1cblxuICB2YWxpZGF0ZVBhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcpOiBQYXNzd29yZFZhbGlkYXRpb25TdGF0dXMge1xuICAgIGNvbnN0IHN0YXR1czogUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWwgPSB7XG4gICAgICBpc1ZhbGlkOiB0cnVlLFxuICAgICAgcGFzc3dvcmRQb2xpY3k6IHRoaXNcbiAgICB9O1xuXG4gICAgLy8gQ2hlY2sgdGhlIHBhc3N3b3JkIGxlbmd0aCBhbmQgY2hhcmFjdGVyIG9wdGlvbnMuXG4gICAgdGhpcy52YWxpZGF0ZVBhc3N3b3JkTGVuZ3RoT3B0aW9ucyhwYXNzd29yZCwgc3RhdHVzKTtcbiAgICB0aGlzLnZhbGlkYXRlUGFzc3dvcmRDaGFyYWN0ZXJPcHRpb25zKHBhc3N3b3JkLCBzdGF0dXMpO1xuXG4gICAgLy8gQ29tYmluZSB0aGUgc3RhdHVzIGludG8gc2luZ2xlIGlzVmFsaWQgcHJvcGVydHkuXG4gICAgc3RhdHVzLmlzVmFsaWQgJiY9IHN0YXR1cy5tZWV0c01pblBhc3N3b3JkTGVuZ3RoID8/IHRydWU7XG4gICAgc3RhdHVzLmlzVmFsaWQgJiY9IHN0YXR1cy5tZWV0c01heFBhc3N3b3JkTGVuZ3RoID8/IHRydWU7XG4gICAgc3RhdHVzLmlzVmFsaWQgJiY9IHN0YXR1cy5jb250YWluc0xvd2VyY2FzZUxldHRlciA/PyB0cnVlO1xuICAgIHN0YXR1cy5pc1ZhbGlkICYmPSBzdGF0dXMuY29udGFpbnNVcHBlcmNhc2VMZXR0ZXIgPz8gdHJ1ZTtcbiAgICBzdGF0dXMuaXNWYWxpZCAmJj0gc3RhdHVzLmNvbnRhaW5zTnVtZXJpY0NoYXJhY3RlciA/PyB0cnVlO1xuICAgIHN0YXR1cy5pc1ZhbGlkICYmPSBzdGF0dXMuY29udGFpbnNOb25BbHBoYW51bWVyaWNDaGFyYWN0ZXIgPz8gdHJ1ZTtcblxuICAgIHJldHVybiBzdGF0dXM7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoYXQgdGhlIHBhc3N3b3JkIG1lZXRzIHRoZSBsZW5ndGggb3B0aW9ucyBmb3IgdGhlIHBvbGljeS5cbiAgICpcbiAgICogQHBhcmFtIHBhc3N3b3JkIFBhc3N3b3JkIHRvIHZhbGlkYXRlLlxuICAgKiBAcGFyYW0gc3RhdHVzIFZhbGlkYXRpb24gc3RhdHVzLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVBhc3N3b3JkTGVuZ3RoT3B0aW9ucyhcbiAgICBwYXNzd29yZDogc3RyaW5nLFxuICAgIHN0YXR1czogUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgbWluUGFzc3dvcmRMZW5ndGggPSB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5taW5QYXNzd29yZExlbmd0aDtcbiAgICBjb25zdCBtYXhQYXNzd29yZExlbmd0aCA9IHRoaXMuY3VzdG9tU3RyZW5ndGhPcHRpb25zLm1heFBhc3N3b3JkTGVuZ3RoO1xuICAgIGlmIChtaW5QYXNzd29yZExlbmd0aCkge1xuICAgICAgc3RhdHVzLm1lZXRzTWluUGFzc3dvcmRMZW5ndGggPSBwYXNzd29yZC5sZW5ndGggPj0gbWluUGFzc3dvcmRMZW5ndGg7XG4gICAgfVxuICAgIGlmIChtYXhQYXNzd29yZExlbmd0aCkge1xuICAgICAgc3RhdHVzLm1lZXRzTWF4UGFzc3dvcmRMZW5ndGggPSBwYXNzd29yZC5sZW5ndGggPD0gbWF4UGFzc3dvcmRMZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGF0IHRoZSBwYXNzd29yZCBtZWV0cyB0aGUgY2hhcmFjdGVyIG9wdGlvbnMgZm9yIHRoZSBwb2xpY3kuXG4gICAqXG4gICAqIEBwYXJhbSBwYXNzd29yZCBQYXNzd29yZCB0byB2YWxpZGF0ZS5cbiAgICogQHBhcmFtIHN0YXR1cyBWYWxpZGF0aW9uIHN0YXR1cy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVQYXNzd29yZENoYXJhY3Rlck9wdGlvbnMoXG4gICAgcGFzc3dvcmQ6IHN0cmluZyxcbiAgICBzdGF0dXM6IFBhc3N3b3JkVmFsaWRhdGlvblN0YXR1c0ludGVybmFsXG4gICk6IHZvaWQge1xuICAgIC8vIEFzc2lnbiBzdGF0dXNlcyBmb3IgcmVxdWlyZW1lbnRzIGV2ZW4gaWYgdGhlIHBhc3N3b3JkIGlzIGFuIGVtcHR5IHN0cmluZy5cbiAgICB0aGlzLnVwZGF0ZVBhc3N3b3JkQ2hhcmFjdGVyT3B0aW9uc1N0YXR1c2VzKFxuICAgICAgc3RhdHVzLFxuICAgICAgLyogY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXI9ICovIGZhbHNlLFxuICAgICAgLyogY29udGFpbnNVcHBlcmNhc2VDaGFyYWN0ZXI9ICovIGZhbHNlLFxuICAgICAgLyogY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyPSAqLyBmYWxzZSxcbiAgICAgIC8qIGNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyPSAqLyBmYWxzZVxuICAgICk7XG5cbiAgICBsZXQgcGFzc3dvcmRDaGFyO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFzc3dvcmQubGVuZ3RoOyBpKyspIHtcbiAgICAgIHBhc3N3b3JkQ2hhciA9IHBhc3N3b3JkLmNoYXJBdChpKTtcbiAgICAgIHRoaXMudXBkYXRlUGFzc3dvcmRDaGFyYWN0ZXJPcHRpb25zU3RhdHVzZXMoXG4gICAgICAgIHN0YXR1cyxcbiAgICAgICAgLyogY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXI9ICovIHBhc3N3b3JkQ2hhciA+PSAnYScgJiZcbiAgICAgICAgICBwYXNzd29yZENoYXIgPD0gJ3onLFxuICAgICAgICAvKiBjb250YWluc1VwcGVyY2FzZUNoYXJhY3Rlcj0gKi8gcGFzc3dvcmRDaGFyID49ICdBJyAmJlxuICAgICAgICAgIHBhc3N3b3JkQ2hhciA8PSAnWicsXG4gICAgICAgIC8qIGNvbnRhaW5zTnVtZXJpY0NoYXJhY3Rlcj0gKi8gcGFzc3dvcmRDaGFyID49ICcwJyAmJlxuICAgICAgICAgIHBhc3N3b3JkQ2hhciA8PSAnOScsXG4gICAgICAgIC8qIGNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyPSAqLyB0aGlzLmFsbG93ZWROb25BbHBoYW51bWVyaWNDaGFyYWN0ZXJzLmluY2x1ZGVzKFxuICAgICAgICAgIHBhc3N3b3JkQ2hhclxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBydW5uaW5nIHZhbGlkYXRpb24gc3RhdHVzIHdpdGggdGhlIHN0YXR1c2VzIGZvciB0aGUgY2hhcmFjdGVyIG9wdGlvbnMuXG4gICAqIEV4cGVjdGVkIHRvIGJlIGNhbGxlZCBlYWNoIHRpbWUgYSBjaGFyYWN0ZXIgaXMgcHJvY2Vzc2VkIHRvIHVwZGF0ZSBlYWNoIG9wdGlvbiBzdGF0dXNcbiAgICogYmFzZWQgb24gdGhlIGN1cnJlbnQgY2hhcmFjdGVyLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdHVzIFZhbGlkYXRpb24gc3RhdHVzLlxuICAgKiBAcGFyYW0gY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXIgV2hldGhlciB0aGUgY2hhcmFjdGVyIGlzIGEgbG93ZXJjYXNlIGxldHRlci5cbiAgICogQHBhcmFtIGNvbnRhaW5zVXBwZXJjYXNlQ2hhcmFjdGVyIFdoZXRoZXIgdGhlIGNoYXJhY3RlciBpcyBhbiB1cHBlcmNhc2UgbGV0dGVyLlxuICAgKiBAcGFyYW0gY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyIFdoZXRoZXIgdGhlIGNoYXJhY3RlciBpcyBhIG51bWVyaWMgY2hhcmFjdGVyLlxuICAgKiBAcGFyYW0gY29udGFpbnNOb25BbHBoYW51bWVyaWNDaGFyYWN0ZXIgV2hldGhlciB0aGUgY2hhcmFjdGVyIGlzIGEgbm9uLWFscGhhbnVtZXJpYyBjaGFyYWN0ZXIuXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZVBhc3N3b3JkQ2hhcmFjdGVyT3B0aW9uc1N0YXR1c2VzKFxuICAgIHN0YXR1czogUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWwsXG4gICAgY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXI6IGJvb2xlYW4sXG4gICAgY29udGFpbnNVcHBlcmNhc2VDaGFyYWN0ZXI6IGJvb2xlYW4sXG4gICAgY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyOiBib29sZWFuLFxuICAgIGNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyOiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIGlmICh0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUxldHRlcikge1xuICAgICAgc3RhdHVzLmNvbnRhaW5zTG93ZXJjYXNlTGV0dGVyIHx8PSBjb250YWluc0xvd2VyY2FzZUNoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHRoaXMuY3VzdG9tU3RyZW5ndGhPcHRpb25zLmNvbnRhaW5zVXBwZXJjYXNlTGV0dGVyKSB7XG4gICAgICBzdGF0dXMuY29udGFpbnNVcHBlcmNhc2VMZXR0ZXIgfHw9IGNvbnRhaW5zVXBwZXJjYXNlQ2hhcmFjdGVyO1xuICAgIH1cbiAgICBpZiAodGhpcy5jdXN0b21TdHJlbmd0aE9wdGlvbnMuY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyKSB7XG4gICAgICBzdGF0dXMuY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyIHx8PSBjb250YWluc051bWVyaWNDaGFyYWN0ZXI7XG4gICAgfVxuICAgIGlmICh0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3Rlcikge1xuICAgICAgc3RhdHVzLmNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyIHx8PVxuICAgICAgICBjb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlcjtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBfaXNGaXJlYmFzZVNlcnZlckFwcCxcbiAgX0ZpcmViYXNlU2VydmljZSxcbiAgRmlyZWJhc2VBcHBcbn0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBQcm92aWRlciB9IGZyb20gJ0BmaXJlYmFzZS9jb21wb25lbnQnO1xuaW1wb3J0IHsgQXBwQ2hlY2tJbnRlcm5hbENvbXBvbmVudE5hbWUgfSBmcm9tICdAZmlyZWJhc2UvYXBwLWNoZWNrLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHtcbiAgQXV0aCxcbiAgQXV0aEVycm9yTWFwLFxuICBBdXRoU2V0dGluZ3MsXG4gIEVtdWxhdG9yQ29uZmlnLFxuICBOZXh0T3JPYnNlcnZlcixcbiAgUGVyc2lzdGVuY2UsXG4gIFBvcHVwUmVkaXJlY3RSZXNvbHZlcixcbiAgVXNlcixcbiAgVXNlckNyZWRlbnRpYWwsXG4gIENvbXBsZXRlRm4sXG4gIEVycm9yRm4sXG4gIE5leHRGbixcbiAgVW5zdWJzY3JpYmUsXG4gIFBhc3N3b3JkVmFsaWRhdGlvblN0YXR1c1xufSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlU3Vic2NyaWJlLFxuICBFcnJvckZhY3RvcnksXG4gIEZpcmViYXNlRXJyb3IsXG4gIGdldE1vZHVsYXJJbnN0YW5jZSxcbiAgT2JzZXJ2ZXIsXG4gIFN1YnNjcmliZVxufSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7IEF1dGhJbnRlcm5hbCwgQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7IFBvcHVwUmVkaXJlY3RSZXNvbHZlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcG9wdXBfcmVkaXJlY3QnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQge1xuICBBdXRoRXJyb3JDb2RlLFxuICBBdXRoRXJyb3JQYXJhbXMsXG4gIEVycm9yTWFwUmV0cmlldmVyLFxuICBfREVGQVVMVF9BVVRIX0VSUk9SX0ZBQ1RPUllcbn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IFBlcnNpc3RlbmNlSW50ZXJuYWwgfSBmcm9tICcuLi9wZXJzaXN0ZW5jZSc7XG5pbXBvcnQge1xuICBLZXlOYW1lLFxuICBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyXG59IGZyb20gJy4uL3BlcnNpc3RlbmNlL3BlcnNpc3RlbmNlX3VzZXJfbWFuYWdlcic7XG5pbXBvcnQgeyBfcmVsb2FkV2l0aG91dFNhdmluZyB9IGZyb20gJy4uL3VzZXIvcmVsb2FkJztcbmltcG9ydCB7XG4gIF9hc3NlcnQsXG4gIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yXG59IGZyb20gJy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7IF9nZXRJbnN0YW5jZSB9IGZyb20gJy4uL3V0aWwvaW5zdGFudGlhdG9yJztcbmltcG9ydCB7IF9nZXRVc2VyTGFuZ3VhZ2UgfSBmcm9tICcuLi91dGlsL25hdmlnYXRvcic7XG5pbXBvcnQgeyBfZ2V0Q2xpZW50VmVyc2lvbiB9IGZyb20gJy4uL3V0aWwvdmVyc2lvbic7XG5pbXBvcnQgeyBIdHRwSGVhZGVyIH0gZnJvbSAnLi4vLi4vYXBpJztcbmltcG9ydCB7XG4gIFJldm9rZVRva2VuUmVxdWVzdCxcbiAgVG9rZW5UeXBlLFxuICByZXZva2VUb2tlblxufSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vdG9rZW4nO1xuaW1wb3J0IHsgQXV0aE1pZGRsZXdhcmVRdWV1ZSB9IGZyb20gJy4vbWlkZGxld2FyZSc7XG5pbXBvcnQgeyBSZWNhcHRjaGFDb25maWcgfSBmcm9tICcuLi8uLi9wbGF0Zm9ybV9icm93c2VyL3JlY2FwdGNoYS9yZWNhcHRjaGEnO1xuaW1wb3J0IHsgX2xvZ1dhcm4gfSBmcm9tICcuLi91dGlsL2xvZyc7XG5pbXBvcnQgeyBfZ2V0UGFzc3dvcmRQb2xpY3kgfSBmcm9tICcuLi8uLi9hcGkvcGFzc3dvcmRfcG9saWN5L2dldF9wYXNzd29yZF9wb2xpY3knO1xuaW1wb3J0IHsgUGFzc3dvcmRQb2xpY3lJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3Bhc3N3b3JkX3BvbGljeSc7XG5pbXBvcnQgeyBQYXNzd29yZFBvbGljeUltcGwgfSBmcm9tICcuL3Bhc3N3b3JkX3BvbGljeV9pbXBsJztcbmltcG9ydCB7IGdldEFjY291bnRJbmZvIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IFVzZXJJbXBsIH0gZnJvbSAnLi4vdXNlci91c2VyX2ltcGwnO1xuXG5pbnRlcmZhY2UgQXN5bmNBY3Rpb24ge1xuICAoKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gRGVmYXVsdENvbmZpZyB7XG4gIFRPS0VOX0FQSV9IT1NUID0gJ3NlY3VyZXRva2VuLmdvb2dsZWFwaXMuY29tJyxcbiAgQVBJX0hPU1QgPSAnaWRlbnRpdHl0b29sa2l0Lmdvb2dsZWFwaXMuY29tJyxcbiAgQVBJX1NDSEVNRSA9ICdodHRwcydcbn1cblxuZXhwb3J0IGNsYXNzIEF1dGhJbXBsIGltcGxlbWVudHMgQXV0aEludGVybmFsLCBfRmlyZWJhc2VTZXJ2aWNlIHtcbiAgY3VycmVudFVzZXI6IFVzZXIgfCBudWxsID0gbnVsbDtcbiAgZW11bGF0b3JDb25maWc6IEVtdWxhdG9yQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgb3BlcmF0aW9ucyA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBwcml2YXRlIHBlcnNpc3RlbmNlTWFuYWdlcj86IFBlcnNpc3RlbmNlVXNlck1hbmFnZXI7XG4gIHByaXZhdGUgcmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXI/OiBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyO1xuICBwcml2YXRlIGF1dGhTdGF0ZVN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb248VXNlcj4odGhpcyk7XG4gIHByaXZhdGUgaWRUb2tlblN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb248VXNlcj4odGhpcyk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmVmb3JlU3RhdGVRdWV1ZSA9IG5ldyBBdXRoTWlkZGxld2FyZVF1ZXVlKHRoaXMpO1xuICBwcml2YXRlIHJlZGlyZWN0VXNlcjogVXNlckludGVybmFsIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaXNQcm9hY3RpdmVSZWZyZXNoRW5hYmxlZCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWRvbmx5IEVYUEVDVEVEX1BBU1NXT1JEX1BPTElDWV9TQ0hFTUFfVkVSU0lPTjogbnVtYmVyID0gMTtcblxuICAvLyBBbnkgbmV0d29yayBjYWxscyB3aWxsIHNldCB0aGlzIHRvIHRydWUgYW5kIHByZXZlbnQgc3Vic2VxdWVudCBlbXVsYXRvclxuICAvLyBpbml0aWFsaXphdGlvblxuICBfY2FuSW5pdEVtdWxhdG9yID0gdHJ1ZTtcbiAgX2lzSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgX2RlbGV0ZWQgPSBmYWxzZTtcbiAgX2luaXRpYWxpemF0aW9uUHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuICBfcG9wdXBSZWRpcmVjdFJlc29sdmVyOiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJJbnRlcm5hbCB8IG51bGwgPSBudWxsO1xuICBfZXJyb3JGYWN0b3J5OiBFcnJvckZhY3Rvcnk8QXV0aEVycm9yQ29kZSwgQXV0aEVycm9yUGFyYW1zPiA9XG4gICAgX0RFRkFVTFRfQVVUSF9FUlJPUl9GQUNUT1JZO1xuICBfYWdlbnRSZWNhcHRjaGFDb25maWc6IFJlY2FwdGNoYUNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBfdGVuYW50UmVjYXB0Y2hhQ29uZmlnczogUmVjb3JkPHN0cmluZywgUmVjYXB0Y2hhQ29uZmlnPiA9IHt9O1xuICBfcHJvamVjdFBhc3N3b3JkUG9saWN5OiBQYXNzd29yZFBvbGljeUludGVybmFsIHwgbnVsbCA9IG51bGw7XG4gIF90ZW5hbnRQYXNzd29yZFBvbGljaWVzOiBSZWNvcmQ8c3RyaW5nLCBQYXNzd29yZFBvbGljeUludGVybmFsPiA9IHt9O1xuICBfcmVzb2x2ZVBlcnNpc3RlbmNlTWFuYWdlckF2YWlsYWJsZTpcbiAgICB8ICgodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZClcbiAgICB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgX3BlcnNpc3RlbmNlTWFuYWdlckF2YWlsYWJsZTogUHJvbWlzZTx2b2lkPjtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8vIFRyYWNrcyB0aGUgbGFzdCBub3RpZmllZCBVSUQgZm9yIHN0YXRlIGNoYW5nZSBsaXN0ZW5lcnMgdG8gcHJldmVudFxuICAvLyByZXBlYXRlZCBjYWxscyB0byB0aGUgY2FsbGJhY2tzLiBVbmRlZmluZWQgbWVhbnMgaXQncyBuZXZlciBiZWVuXG4gIC8vIGNhbGxlZCwgd2hlcmVhcyBudWxsIG1lYW5zIGl0J3MgYmVlbiBjYWxsZWQgd2l0aCBhIHNpZ25lZCBvdXQgdXNlclxuICBwcml2YXRlIGxhc3ROb3RpZmllZFVpZDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBsYW5ndWFnZUNvZGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICB0ZW5hbnRJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHNldHRpbmdzOiBBdXRoU2V0dGluZ3MgPSB7IGFwcFZlcmlmaWNhdGlvbkRpc2FibGVkRm9yVGVzdGluZzogZmFsc2UgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgYXBwOiBGaXJlYmFzZUFwcCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhlYXJ0YmVhdFNlcnZpY2VQcm92aWRlcjogUHJvdmlkZXI8J2hlYXJ0YmVhdCc+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXBwQ2hlY2tTZXJ2aWNlUHJvdmlkZXI6IFByb3ZpZGVyPEFwcENoZWNrSW50ZXJuYWxDb21wb25lbnROYW1lPixcbiAgICBwdWJsaWMgcmVhZG9ubHkgY29uZmlnOiBDb25maWdJbnRlcm5hbFxuICApIHtcbiAgICB0aGlzLm5hbWUgPSBhcHAubmFtZTtcbiAgICB0aGlzLmNsaWVudFZlcnNpb24gPSBjb25maWcuc2RrQ2xpZW50VmVyc2lvbjtcbiAgICAvLyBUT0RPKGphbWVzZGFuaWVscykgZXhwbG9yZSBsZXNzIGhhY2t5IHdheSB0byBkbyB0aGlzLCBjb29raWUgYXV0aGVudGljYXRpb24gbmVlZHNcbiAgICAvLyBwZXJzaXN0ZW5jZU1hbmFuZ2VyIHRvIGJlIGF2YWlsYWJsZS4gc2VlIF9nZXRGaW5hbFRhcmdldCBmb3IgbW9yZSBjb250ZXh0XG4gICAgdGhpcy5fcGVyc2lzdGVuY2VNYW5hZ2VyQXZhaWxhYmxlID0gbmV3IFByb21pc2U8dm9pZD4oXG4gICAgICByZXNvbHZlID0+ICh0aGlzLl9yZXNvbHZlUGVyc2lzdGVuY2VNYW5hZ2VyQXZhaWxhYmxlID0gcmVzb2x2ZSlcbiAgICApO1xuICB9XG5cbiAgX2luaXRpYWxpemVXaXRoUGVyc2lzdGVuY2UoXG4gICAgcGVyc2lzdGVuY2VIaWVyYXJjaHk6IFBlcnNpc3RlbmNlSW50ZXJuYWxbXSxcbiAgICBwb3B1cFJlZGlyZWN0UmVzb2x2ZXI/OiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHBvcHVwUmVkaXJlY3RSZXNvbHZlcikge1xuICAgICAgdGhpcy5fcG9wdXBSZWRpcmVjdFJlc29sdmVyID0gX2dldEluc3RhbmNlKHBvcHVwUmVkaXJlY3RSZXNvbHZlcik7XG4gICAgfVxuXG4gICAgLy8gSGF2ZSB0byBjaGVjayBmb3IgYXBwIGRlbGV0aW9uIHRocm91Z2hvdXQgaW5pdGlhbGl6YXRpb24gKGFmdGVyIGVhY2hcbiAgICAvLyBwcm9taXNlIHJlc29sdXRpb24pXG4gICAgdGhpcy5faW5pdGlhbGl6YXRpb25Qcm9taXNlID0gdGhpcy5xdWV1ZShhc3luYyAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fZGVsZXRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyc2lzdGVuY2VNYW5hZ2VyID0gYXdhaXQgUGVyc2lzdGVuY2VVc2VyTWFuYWdlci5jcmVhdGUoXG4gICAgICAgIHRoaXMsXG4gICAgICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5XG4gICAgICApO1xuICAgICAgdGhpcy5fcmVzb2x2ZVBlcnNpc3RlbmNlTWFuYWdlckF2YWlsYWJsZT8uKCk7XG5cbiAgICAgIGlmICh0aGlzLl9kZWxldGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgcmVzb2x2ZXIgZWFybHkgaWYgbmVjZXNzYXJ5IChvbmx5IGFwcGxpY2FibGUgdG8gd2ViOlxuICAgICAgLy8gdGhpcyB3aWxsIGNhdXNlIHRoZSBpZnJhbWUgdG8gbG9hZCBpbW1lZGlhdGVseSBpbiBjZXJ0YWluIGNhc2VzKVxuICAgICAgaWYgKHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlcj8uX3Nob3VsZEluaXRQcm9hY3RpdmVseSkge1xuICAgICAgICAvLyBJZiB0aGlzIGZhaWxzLCBkb24ndCBoYWx0IGF1dGggbG9hZGluZ1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlci5faW5pdGlhbGl6ZSh0aGlzKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIC8qIElnbm9yZSB0aGUgZXJyb3IgKi9cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVDdXJyZW50VXNlcihwb3B1cFJlZGlyZWN0UmVzb2x2ZXIpO1xuXG4gICAgICB0aGlzLmxhc3ROb3RpZmllZFVpZCA9IHRoaXMuY3VycmVudFVzZXI/LnVpZCB8fCBudWxsO1xuXG4gICAgICBpZiAodGhpcy5fZGVsZXRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2luaXRpYWxpemF0aW9uUHJvbWlzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGUgcGVyc2lzdGVuY2UgaXMgY2hhbmdlZCBpbiBhbm90aGVyIHdpbmRvdywgdGhlIHVzZXIgbWFuYWdlciB3aWxsIGxldCB1cyBrbm93XG4gICAqL1xuICBhc3luYyBfb25TdG9yYWdlRXZlbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuX2RlbGV0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5hc3NlcnRlZFBlcnNpc3RlbmNlLmdldEN1cnJlbnRVc2VyKCk7XG5cbiAgICBpZiAoIXRoaXMuY3VycmVudFVzZXIgJiYgIXVzZXIpIHtcbiAgICAgIC8vIE5vIGNoYW5nZSwgZG8gbm90aGluZyAod2FzIHNpZ25lZCBvdXQgYW5kIHJlbWFpbmVkIHNpZ25lZCBvdXQpLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBzYW1lIHVzZXIgaXMgdG8gYmUgc3luY2hyb25pemVkLlxuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyICYmIHVzZXIgJiYgdGhpcy5jdXJyZW50VXNlci51aWQgPT09IHVzZXIudWlkKSB7XG4gICAgICAvLyBEYXRhIHVwZGF0ZSwgc2ltcGx5IGNvcHkgZGF0YSBjaGFuZ2VzLlxuICAgICAgdGhpcy5fY3VycmVudFVzZXIuX2Fzc2lnbih1c2VyKTtcbiAgICAgIC8vIElmIHRva2VucyBjaGFuZ2VkIGZyb20gcHJldmlvdXMgdXNlciB0b2tlbnMsIHRoaXMgd2lsbCB0cmlnZ2VyXG4gICAgICAvLyBub3RpZnlBdXRoTGlzdGVuZXJzXy5cbiAgICAgIGF3YWl0IHRoaXMuY3VycmVudFVzZXIuZ2V0SWRUb2tlbigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBjdXJyZW50IEF1dGggc3RhdGUuIEVpdGhlciBhIG5ldyBsb2dpbiBvciBsb2dvdXQuXG4gICAgLy8gU2tpcCBibG9ja2luZyBjYWxsYmFja3MsIHRoZXkgc2hvdWxkIG5vdCBhcHBseSB0byBhIGNoYW5nZSBpbiBhbm90aGVyIHRhYi5cbiAgICBhd2FpdCB0aGlzLl91cGRhdGVDdXJyZW50VXNlcih1c2VyLCAvKiBza2lwQmVmb3JlU3RhdGVDYWxsYmFja3MgKi8gdHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVDdXJyZW50VXNlckZyb21JZFRva2VuKFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBnZXRBY2NvdW50SW5mbyh0aGlzLCB7IGlkVG9rZW4gfSk7XG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgVXNlckltcGwuX2Zyb21HZXRBY2NvdW50SW5mb1Jlc3BvbnNlKFxuICAgICAgICB0aGlzLFxuICAgICAgICByZXNwb25zZSxcbiAgICAgICAgaWRUb2tlblxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuZGlyZWN0bHlTZXRDdXJyZW50VXNlcih1c2VyKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ0ZpcmViYXNlU2VydmVyQXBwIGNvdWxkIG5vdCBsb2dpbiB1c2VyIHdpdGggcHJvdmlkZWQgYXV0aElkVG9rZW46ICcsXG4gICAgICAgIGVyclxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuZGlyZWN0bHlTZXRDdXJyZW50VXNlcihudWxsKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVDdXJyZW50VXNlcihcbiAgICBwb3B1cFJlZGlyZWN0UmVzb2x2ZXI/OiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKHRoaXMuYXBwKSkge1xuICAgICAgY29uc3QgaWRUb2tlbiA9IHRoaXMuYXBwLnNldHRpbmdzLmF1dGhJZFRva2VuO1xuICAgICAgaWYgKGlkVG9rZW4pIHtcbiAgICAgICAgLy8gU3RhcnQgdGhlIGF1dGggb3BlcmF0aW9uIGluIHRoZSBuZXh0IHRpY2sgdG8gYWxsb3cgYSBtb21lbnQgZm9yIHRoZSBjdXN0b21lcidzIGFwcCB0b1xuICAgICAgICAvLyBhdHRhY2ggYW4gZW11bGF0b3IsIGlmIGRlc2lyZWQuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPihyZXNvbHZlID0+IHtcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVDdXJyZW50VXNlckZyb21JZFRva2VuKGlkVG9rZW4pLnRoZW4oXG4gICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICAgIHJlc29sdmVcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIobnVsbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmlyc3QgY2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYSBwZW5kaW5nIHJlZGlyZWN0IGV2ZW50LlxuICAgIGNvbnN0IHByZXZpb3VzbHlTdG9yZWRVc2VyID1cbiAgICAgIChhd2FpdCB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2UuZ2V0Q3VycmVudFVzZXIoKSkgYXMgVXNlckludGVybmFsIHwgbnVsbDtcbiAgICBsZXQgZnV0dXJlQ3VycmVudFVzZXIgPSBwcmV2aW91c2x5U3RvcmVkVXNlcjtcbiAgICBsZXQgbmVlZHNUb2NoZWNrTWlkZGxld2FyZSA9IGZhbHNlO1xuICAgIGlmIChwb3B1cFJlZGlyZWN0UmVzb2x2ZXIgJiYgdGhpcy5jb25maWcuYXV0aERvbWFpbikge1xuICAgICAgYXdhaXQgdGhpcy5nZXRPckluaXRSZWRpcmVjdFBlcnNpc3RlbmNlTWFuYWdlcigpO1xuICAgICAgY29uc3QgcmVkaXJlY3RVc2VyRXZlbnRJZCA9IHRoaXMucmVkaXJlY3RVc2VyPy5fcmVkaXJlY3RFdmVudElkO1xuICAgICAgY29uc3Qgc3RvcmVkVXNlckV2ZW50SWQgPSBmdXR1cmVDdXJyZW50VXNlcj8uX3JlZGlyZWN0RXZlbnRJZDtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudHJ5UmVkaXJlY3RTaWduSW4ocG9wdXBSZWRpcmVjdFJlc29sdmVyKTtcblxuICAgICAgLy8gSWYgdGhlIHN0b3JlZCB1c2VyIChpLmUuIHRoZSBvbGQgXCJjdXJyZW50VXNlclwiKSBoYXMgYSByZWRpcmVjdElkIHRoYXRcbiAgICAgIC8vIG1hdGNoZXMgdGhlIHJlZGlyZWN0IHVzZXIsIHRoZW4gd2Ugd2FudCB0byBpbml0aWFsbHkgc2lnbiBpbiB3aXRoIHRoZVxuICAgICAgLy8gbmV3IHVzZXIgb2JqZWN0IGZyb20gcmVzdWx0LlxuICAgICAgLy8gVE9ETyhzYW1naG8pOiBNb3JlIHRob3JvdWdobHkgdGVzdCBhbGwgb2YgdGhpc1xuICAgICAgaWYgKFxuICAgICAgICAoIXJlZGlyZWN0VXNlckV2ZW50SWQgfHwgcmVkaXJlY3RVc2VyRXZlbnRJZCA9PT0gc3RvcmVkVXNlckV2ZW50SWQpICYmXG4gICAgICAgIHJlc3VsdD8udXNlclxuICAgICAgKSB7XG4gICAgICAgIGZ1dHVyZUN1cnJlbnRVc2VyID0gcmVzdWx0LnVzZXIgYXMgVXNlckludGVybmFsO1xuICAgICAgICBuZWVkc1RvY2hlY2tNaWRkbGV3YXJlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiBubyB1c2VyIGluIHBlcnNpc3RlbmNlLCB0aGVyZSBpcyBubyBjdXJyZW50IHVzZXIuIFNldCB0byBudWxsLlxuICAgIGlmICghZnV0dXJlQ3VycmVudFVzZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIobnVsbCk7XG4gICAgfVxuXG4gICAgaWYgKCFmdXR1cmVDdXJyZW50VXNlci5fcmVkaXJlY3RFdmVudElkKSB7XG4gICAgICAvLyBUaGlzIGlzbid0IGEgcmVkaXJlY3QgbGluayBvcGVyYXRpb24sIHdlIGNhbiByZWxvYWQgYW5kIGJhaWwuXG4gICAgICAvLyBGaXJzdCB0aG91Z2gsIGVuc3VyZSB0aGF0IHdlIGNoZWNrIHRoZSBtaWRkbGV3YXJlIGlzIGhhcHB5LlxuICAgICAgaWYgKG5lZWRzVG9jaGVja01pZGRsZXdhcmUpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmJlZm9yZVN0YXRlUXVldWUucnVuTWlkZGxld2FyZShmdXR1cmVDdXJyZW50VXNlcik7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBmdXR1cmVDdXJyZW50VXNlciA9IHByZXZpb3VzbHlTdG9yZWRVc2VyO1xuICAgICAgICAgIC8vIFdlIGtub3cgdGhpcyBpcyBhdmFpbGFibGUgc2luY2UgdGhlIGJpdCBpcyBvbmx5IHNldCB3aGVuIHRoZVxuICAgICAgICAgIC8vIHJlc29sdmVyIGlzIGF2YWlsYWJsZVxuICAgICAgICAgIHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlciEuX292ZXJyaWRlUmVkaXJlY3RSZXN1bHQodGhpcywgKCkgPT5cbiAgICAgICAgICAgIFByb21pc2UucmVqZWN0KGUpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZnV0dXJlQ3VycmVudFVzZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVsb2FkQW5kU2V0Q3VycmVudFVzZXJPckNsZWFyKGZ1dHVyZUN1cnJlbnRVc2VyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIobnVsbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2Fzc2VydCh0aGlzLl9wb3B1cFJlZGlyZWN0UmVzb2x2ZXIsIHRoaXMsIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IpO1xuICAgIGF3YWl0IHRoaXMuZ2V0T3JJbml0UmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIoKTtcblxuICAgIC8vIElmIHRoZSByZWRpcmVjdCB1c2VyJ3MgZXZlbnQgSUQgbWF0Y2hlcyB0aGUgY3VycmVudCB1c2VyJ3MgZXZlbnQgSUQsXG4gICAgLy8gRE8gTk9UIHJlbG9hZCB0aGUgY3VycmVudCB1c2VyLCBvdGhlcndpc2UgdGhleSdsbCBiZSBjbGVhcmVkIGZyb20gc3RvcmFnZS5cbiAgICAvLyBUaGlzIGlzIGltcG9ydGFudCBmb3IgdGhlIHJlYXV0aGVudGljYXRlV2l0aFJlZGlyZWN0KCkgZmxvdy5cbiAgICBpZiAoXG4gICAgICB0aGlzLnJlZGlyZWN0VXNlciAmJlxuICAgICAgdGhpcy5yZWRpcmVjdFVzZXIuX3JlZGlyZWN0RXZlbnRJZCA9PT0gZnV0dXJlQ3VycmVudFVzZXIuX3JlZGlyZWN0RXZlbnRJZFxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuZGlyZWN0bHlTZXRDdXJyZW50VXNlcihmdXR1cmVDdXJyZW50VXNlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVsb2FkQW5kU2V0Q3VycmVudFVzZXJPckNsZWFyKGZ1dHVyZUN1cnJlbnRVc2VyKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdHJ5UmVkaXJlY3RTaWduSW4oXG4gICAgcmVkaXJlY3RSZXNvbHZlcjogUG9wdXBSZWRpcmVjdFJlc29sdmVyXG4gICk6IFByb21pc2U8VXNlckNyZWRlbnRpYWwgfCBudWxsPiB7XG4gICAgLy8gVGhlIHJlZGlyZWN0IHVzZXIgbmVlZHMgdG8gYmUgY2hlY2tlZCAoYW5kIHNpZ25lZCBpbiBpZiBhdmFpbGFibGUpXG4gICAgLy8gZHVyaW5nIGF1dGggaW5pdGlhbGl6YXRpb24uIEFsbCBvZiB0aGUgbm9ybWFsIHNpZ24gaW4gYW5kIGxpbmsvcmVhdXRoXG4gICAgLy8gZmxvd3MgY2FsbCBiYWNrIGludG8gYXV0aCBhbmQgcHVzaCB0aGluZ3Mgb250byB0aGUgcHJvbWlzZSBxdWV1ZS4gV2VcbiAgICAvLyBuZWVkIHRvIGF3YWl0IHRoZSByZXN1bHQgb2YgdGhlIHJlZGlyZWN0IHNpZ24gaW4gKmluc2lkZSB0aGUgcHJvbWlzZVxuICAgIC8vIHF1ZXVlKi4gVGhpcyBwcmVzZW50cyBhIHByb2JsZW06IHdlIHJ1biBpbnRvIGRlYWRsb2NrLiBTZWU6XG4gICAgLy8gICAg4pSMPiBbSW5pdGlhbGl6YXRpb25dIOKUgOKUgOKUgOKUgOKUgOKUkFxuICAgIC8vICAgIOKUjD4gWzxvdGhlciBxdWV1ZSB0YXNrcz5dIOKUglxuICAgIC8vICAgIOKUlOKUgCBbZ2V0UmVkaXJlY3RSZXN1bHRdIDzilIDilJhcbiAgICAvLyAgICB3aGVyZSBbXSBhcmUgdGFza3Mgb24gdGhlIHF1ZXVlIGFuZCBhcnJvd3MgZGVub3RlIGF3YWl0c1xuICAgIC8vIEluaXRpYWxpemF0aW9uIHdpbGwgbmV2ZXIgY29tcGxldGUgYmVjYXVzZSBpdCdzIHdhaXRpbmcgb24gc29tZXRoaW5nXG4gICAgLy8gdGhhdCdzIHdhaXRpbmcgZm9yIGluaXRpYWxpemF0aW9uIHRvIGNvbXBsZXRlIVxuICAgIC8vXG4gICAgLy8gSW5zdGVhZCwgdGhpcyBtZXRob2QgY2FsbHMgZ2V0UmVkaXJlY3RSZXN1bHQoKSAoc3RvcmVkIGluXG4gICAgLy8gX2NvbXBsZXRlUmVkaXJlY3RGbikgd2l0aCBhbiBvcHRpb25hbCBwYXJhbWV0ZXIgdGhhdCBpbnN0cnVjdHMgYWxsIG9mXG4gICAgLy8gdGhlIHVuZGVybHlpbmcgYXV0aCBvcGVyYXRpb25zIHRvIHNraXAgYW55dGhpbmcgdGhhdCBtdXRhdGVzIGF1dGggc3RhdGUuXG5cbiAgICBsZXQgcmVzdWx0OiBVc2VyQ3JlZGVudGlhbCB8IG51bGwgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICAvLyBXZSBrbm93IHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlciBpcyBzZXQgc2luY2UgcmVkaXJlY3RSZXNvbHZlclxuICAgICAgLy8gaXMgcGFzc2VkIGluLiBUaGUgX2NvbXBsZXRlUmVkaXJlY3RGbiBleHBlY3RzIHRoZSB1bndyYXBwZWQgZXh0ZXJuLlxuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5fcG9wdXBSZWRpcmVjdFJlc29sdmVyIS5fY29tcGxldGVSZWRpcmVjdEZuKFxuICAgICAgICB0aGlzLFxuICAgICAgICByZWRpcmVjdFJlc29sdmVyLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIFN3YWxsb3cgYW55IGVycm9ycyBoZXJlOyB0aGUgY29kZSBjYW4gcmV0cmlldmUgdGhlbSBpblxuICAgICAgLy8gZ2V0UmVkaXJlY3RSZXN1bHQoKS5cbiAgICAgIGF3YWl0IHRoaXMuX3NldFJlZGlyZWN0VXNlcihudWxsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWxvYWRBbmRTZXRDdXJyZW50VXNlck9yQ2xlYXIoXG4gICAgdXNlcjogVXNlckludGVybmFsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBfcmVsb2FkV2l0aG91dFNhdmluZyh1c2VyKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoXG4gICAgICAgIChlIGFzIEZpcmViYXNlRXJyb3IpPy5jb2RlICE9PVxuICAgICAgICBgYXV0aC8ke0F1dGhFcnJvckNvZGUuTkVUV09SS19SRVFVRVNUX0ZBSUxFRH1gXG4gICAgICApIHtcbiAgICAgICAgLy8gU29tZXRoaW5nJ3Mgd3Jvbmcgd2l0aCB0aGUgdXNlcidzIHRva2VuLiBMb2cgdGhlbSBvdXQgYW5kIHJlbW92ZVxuICAgICAgICAvLyB0aGVtIGZyb20gc3RvcmFnZVxuICAgICAgICByZXR1cm4gdGhpcy5kaXJlY3RseVNldEN1cnJlbnRVc2VyKG51bGwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIodXNlcik7XG4gIH1cblxuICB1c2VEZXZpY2VMYW5ndWFnZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxhbmd1YWdlQ29kZSA9IF9nZXRVc2VyTGFuZ3VhZ2UoKTtcbiAgfVxuXG4gIGFzeW5jIF9kZWxldGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5fZGVsZXRlZCA9IHRydWU7XG4gIH1cblxuICBhc3luYyB1cGRhdGVDdXJyZW50VXNlcih1c2VyRXh0ZXJuOiBVc2VyIHwgbnVsbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmFwcCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IodGhpcylcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIFRoZSBwdWJsaWMgdXBkYXRlQ3VycmVudFVzZXIgbWV0aG9kIG5lZWRzIHRvIG1ha2UgYSBjb3B5IG9mIHRoZSB1c2VyLFxuICAgIC8vIGFuZCBhbHNvIGNoZWNrIHRoYXQgdGhlIHByb2plY3QgbWF0Y2hlc1xuICAgIGNvbnN0IHVzZXIgPSB1c2VyRXh0ZXJuXG4gICAgICA/IChnZXRNb2R1bGFySW5zdGFuY2UodXNlckV4dGVybikgYXMgVXNlckludGVybmFsKVxuICAgICAgOiBudWxsO1xuICAgIGlmICh1c2VyKSB7XG4gICAgICBfYXNzZXJ0KFxuICAgICAgICB1c2VyLmF1dGguY29uZmlnLmFwaUtleSA9PT0gdGhpcy5jb25maWcuYXBpS2V5LFxuICAgICAgICB0aGlzLFxuICAgICAgICBBdXRoRXJyb3JDb2RlLklOVkFMSURfQVVUSFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3VwZGF0ZUN1cnJlbnRVc2VyKHVzZXIgJiYgdXNlci5fY2xvbmUodGhpcykpO1xuICB9XG5cbiAgYXN5bmMgX3VwZGF0ZUN1cnJlbnRVc2VyKFxuICAgIHVzZXI6IFVzZXIgfCBudWxsLFxuICAgIHNraXBCZWZvcmVTdGF0ZUNhbGxiYWNrczogYm9vbGVhbiA9IGZhbHNlXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLl9kZWxldGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh1c2VyKSB7XG4gICAgICBfYXNzZXJ0KFxuICAgICAgICB0aGlzLnRlbmFudElkID09PSB1c2VyLnRlbmFudElkLFxuICAgICAgICB0aGlzLFxuICAgICAgICBBdXRoRXJyb3JDb2RlLlRFTkFOVF9JRF9NSVNNQVRDSFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIXNraXBCZWZvcmVTdGF0ZUNhbGxiYWNrcykge1xuICAgICAgYXdhaXQgdGhpcy5iZWZvcmVTdGF0ZVF1ZXVlLnJ1bk1pZGRsZXdhcmUodXNlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucXVldWUoYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgdGhpcy5kaXJlY3RseVNldEN1cnJlbnRVc2VyKHVzZXIgYXMgVXNlckludGVybmFsIHwgbnVsbCk7XG4gICAgICB0aGlzLm5vdGlmeUF1dGhMaXN0ZW5lcnMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHNpZ25PdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKHRoaXMuYXBwKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcih0aGlzKVxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gUnVuIGZpcnN0LCB0byBibG9jayBfc2V0UmVkaXJlY3RVc2VyKCkgaWYgYW55IGNhbGxiYWNrcyBmYWlsLlxuICAgIGF3YWl0IHRoaXMuYmVmb3JlU3RhdGVRdWV1ZS5ydW5NaWRkbGV3YXJlKG51bGwpO1xuICAgIC8vIENsZWFyIHRoZSByZWRpcmVjdCB1c2VyIHdoZW4gc2lnbk91dCBpcyBjYWxsZWRcbiAgICBpZiAodGhpcy5yZWRpcmVjdFBlcnNpc3RlbmNlTWFuYWdlciB8fCB0aGlzLl9wb3B1cFJlZGlyZWN0UmVzb2x2ZXIpIHtcbiAgICAgIGF3YWl0IHRoaXMuX3NldFJlZGlyZWN0VXNlcihudWxsKTtcbiAgICB9XG5cbiAgICAvLyBQcmV2ZW50IGNhbGxiYWNrcyBmcm9tIGJlaW5nIGNhbGxlZCBhZ2FpbiBpbiBfdXBkYXRlQ3VycmVudFVzZXIsIGFzXG4gICAgLy8gdGhleSB3ZXJlIGFscmVhZHkgY2FsbGVkIGluIHRoZSBmaXJzdCBsaW5lLlxuICAgIHJldHVybiB0aGlzLl91cGRhdGVDdXJyZW50VXNlcihudWxsLCAvKiBza2lwQmVmb3JlU3RhdGVDYWxsYmFja3MgKi8gdHJ1ZSk7XG4gIH1cblxuICBzZXRQZXJzaXN0ZW5jZShwZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAodGhpcy5hcHApKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKHRoaXMpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5xdWV1ZShhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2Uuc2V0UGVyc2lzdGVuY2UoX2dldEluc3RhbmNlKHBlcnNpc3RlbmNlKSk7XG4gICAgfSk7XG4gIH1cblxuICBfZ2V0UmVjYXB0Y2hhQ29uZmlnKCk6IFJlY2FwdGNoYUNvbmZpZyB8IG51bGwge1xuICAgIGlmICh0aGlzLnRlbmFudElkID09IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLl9hZ2VudFJlY2FwdGNoYUNvbmZpZztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3RlbmFudFJlY2FwdGNoYUNvbmZpZ3NbdGhpcy50ZW5hbnRJZF07XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgdmFsaWRhdGVQYXNzd29yZChwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxQYXNzd29yZFZhbGlkYXRpb25TdGF0dXM+IHtcbiAgICBpZiAoIXRoaXMuX2dldFBhc3N3b3JkUG9saWN5SW50ZXJuYWwoKSkge1xuICAgICAgYXdhaXQgdGhpcy5fdXBkYXRlUGFzc3dvcmRQb2xpY3koKTtcbiAgICB9XG5cbiAgICAvLyBQYXNzd29yZCBwb2xpY3kgd2lsbCBiZSBkZWZpbmVkIGFmdGVyIGZldGNoaW5nLlxuICAgIGNvbnN0IHBhc3N3b3JkUG9saWN5OiBQYXNzd29yZFBvbGljeUludGVybmFsID1cbiAgICAgIHRoaXMuX2dldFBhc3N3b3JkUG9saWN5SW50ZXJuYWwoKSE7XG5cbiAgICAvLyBDaGVjayB0aGF0IHRoZSBwb2xpY3kgc2NoZW1hIHZlcnNpb24gaXMgc3VwcG9ydGVkIGJ5IHRoZSBTREsuXG4gICAgLy8gVE9ETzogVXBkYXRlIHRoaXMgbG9naWMgdG8gdXNlIGEgbWF4IHN1cHBvcnRlZCBwb2xpY3kgc2NoZW1hIHZlcnNpb24gb25jZSB3ZSBoYXZlIG11bHRpcGxlIHNjaGVtYSB2ZXJzaW9ucy5cbiAgICBpZiAoXG4gICAgICBwYXNzd29yZFBvbGljeS5zY2hlbWFWZXJzaW9uICE9PVxuICAgICAgdGhpcy5FWFBFQ1RFRF9QQVNTV09SRF9QT0xJQ1lfU0NIRU1BX1ZFUlNJT05cbiAgICApIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgdGhpcy5fZXJyb3JGYWN0b3J5LmNyZWF0ZShcbiAgICAgICAgICBBdXRoRXJyb3JDb2RlLlVOU1VQUE9SVEVEX1BBU1NXT1JEX1BPTElDWV9TQ0hFTUFfVkVSU0lPTixcbiAgICAgICAgICB7fVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBwYXNzd29yZFBvbGljeS52YWxpZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKTtcbiAgfVxuXG4gIF9nZXRQYXNzd29yZFBvbGljeUludGVybmFsKCk6IFBhc3N3b3JkUG9saWN5SW50ZXJuYWwgfCBudWxsIHtcbiAgICBpZiAodGhpcy50ZW5hbnRJZCA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3Byb2plY3RQYXNzd29yZFBvbGljeTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3RlbmFudFBhc3N3b3JkUG9saWNpZXNbdGhpcy50ZW5hbnRJZF07XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX3VwZGF0ZVBhc3N3b3JkUG9saWN5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2dldFBhc3N3b3JkUG9saWN5KHRoaXMpO1xuXG4gICAgY29uc3QgcGFzc3dvcmRQb2xpY3k6IFBhc3N3b3JkUG9saWN5SW50ZXJuYWwgPSBuZXcgUGFzc3dvcmRQb2xpY3lJbXBsKFxuICAgICAgcmVzcG9uc2VcbiAgICApO1xuXG4gICAgaWYgKHRoaXMudGVuYW50SWQgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuX3Byb2plY3RQYXNzd29yZFBvbGljeSA9IHBhc3N3b3JkUG9saWN5O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl90ZW5hbnRQYXNzd29yZFBvbGljaWVzW3RoaXMudGVuYW50SWRdID0gcGFzc3dvcmRQb2xpY3k7XG4gICAgfVxuICB9XG5cbiAgX2dldFBlcnNpc3RlbmNlVHlwZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2UucGVyc2lzdGVuY2UudHlwZTtcbiAgfVxuXG4gIF9nZXRQZXJzaXN0ZW5jZSgpOiBQZXJzaXN0ZW5jZUludGVybmFsIHtcbiAgICByZXR1cm4gdGhpcy5hc3NlcnRlZFBlcnNpc3RlbmNlLnBlcnNpc3RlbmNlO1xuICB9XG5cbiAgX3VwZGF0ZUVycm9yTWFwKGVycm9yTWFwOiBBdXRoRXJyb3JNYXApOiB2b2lkIHtcbiAgICB0aGlzLl9lcnJvckZhY3RvcnkgPSBuZXcgRXJyb3JGYWN0b3J5PEF1dGhFcnJvckNvZGUsIEF1dGhFcnJvclBhcmFtcz4oXG4gICAgICAnYXV0aCcsXG4gICAgICAnRmlyZWJhc2UnLFxuICAgICAgKGVycm9yTWFwIGFzIEVycm9yTWFwUmV0cmlldmVyKSgpXG4gICAgKTtcbiAgfVxuXG4gIG9uQXV0aFN0YXRlQ2hhbmdlZChcbiAgICBuZXh0T3JPYnNlcnZlcjogTmV4dE9yT2JzZXJ2ZXI8VXNlcj4sXG4gICAgZXJyb3I/OiBFcnJvckZuLFxuICAgIGNvbXBsZXRlZD86IENvbXBsZXRlRm5cbiAgKTogVW5zdWJzY3JpYmUge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdGVyU3RhdGVMaXN0ZW5lcihcbiAgICAgIHRoaXMuYXV0aFN0YXRlU3Vic2NyaXB0aW9uLFxuICAgICAgbmV4dE9yT2JzZXJ2ZXIsXG4gICAgICBlcnJvcixcbiAgICAgIGNvbXBsZXRlZFxuICAgICk7XG4gIH1cblxuICBiZWZvcmVBdXRoU3RhdGVDaGFuZ2VkKFxuICAgIGNhbGxiYWNrOiAodXNlcjogVXNlciB8IG51bGwpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICAgIG9uQWJvcnQ/OiAoKSA9PiB2b2lkXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICByZXR1cm4gdGhpcy5iZWZvcmVTdGF0ZVF1ZXVlLnB1c2hDYWxsYmFjayhjYWxsYmFjaywgb25BYm9ydCk7XG4gIH1cblxuICBvbklkVG9rZW5DaGFuZ2VkKFxuICAgIG5leHRPck9ic2VydmVyOiBOZXh0T3JPYnNlcnZlcjxVc2VyPixcbiAgICBlcnJvcj86IEVycm9yRm4sXG4gICAgY29tcGxldGVkPzogQ29tcGxldGVGblxuICApOiBVbnN1YnNjcmliZSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJTdGF0ZUxpc3RlbmVyKFxuICAgICAgdGhpcy5pZFRva2VuU3Vic2NyaXB0aW9uLFxuICAgICAgbmV4dE9yT2JzZXJ2ZXIsXG4gICAgICBlcnJvcixcbiAgICAgIGNvbXBsZXRlZFxuICAgICk7XG4gIH1cblxuICBhdXRoU3RhdGVSZWFkeSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKHRoaXMuY3VycmVudFVzZXIpIHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgdW5zdWJzY3JpYmUgPSB0aGlzLm9uQXV0aFN0YXRlQ2hhbmdlZCgoKSA9PiB7XG4gICAgICAgICAgdW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sIHJlamVjdCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV2b2tlcyB0aGUgZ2l2ZW4gYWNjZXNzIHRva2VuLiBDdXJyZW50bHkgb25seSBzdXBwb3J0cyBBcHBsZSBPQXV0aCBhY2Nlc3MgdG9rZW5zLlxuICAgKi9cbiAgYXN5bmMgcmV2b2tlQWNjZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICBjb25zdCBpZFRva2VuID0gYXdhaXQgdGhpcy5jdXJyZW50VXNlci5nZXRJZFRva2VuKCk7XG4gICAgICAvLyBHZW5lcmFsaXplIHRoaXMgdG8gYWNjZXB0IG90aGVyIHByb3ZpZGVycyBvbmNlIHN1cHBvcnRlZC5cbiAgICAgIGNvbnN0IHJlcXVlc3Q6IFJldm9rZVRva2VuUmVxdWVzdCA9IHtcbiAgICAgICAgcHJvdmlkZXJJZDogJ2FwcGxlLmNvbScsXG4gICAgICAgIHRva2VuVHlwZTogVG9rZW5UeXBlLkFDQ0VTU19UT0tFTixcbiAgICAgICAgdG9rZW4sXG4gICAgICAgIGlkVG9rZW5cbiAgICAgIH07XG4gICAgICBpZiAodGhpcy50ZW5hbnRJZCAhPSBudWxsKSB7XG4gICAgICAgIHJlcXVlc3QudGVuYW50SWQgPSB0aGlzLnRlbmFudElkO1xuICAgICAgfVxuICAgICAgYXdhaXQgcmV2b2tlVG9rZW4odGhpcywgcmVxdWVzdCk7XG4gICAgfVxuICB9XG5cbiAgdG9KU09OKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFwaUtleTogdGhpcy5jb25maWcuYXBpS2V5LFxuICAgICAgYXV0aERvbWFpbjogdGhpcy5jb25maWcuYXV0aERvbWFpbixcbiAgICAgIGFwcE5hbWU6IHRoaXMubmFtZSxcbiAgICAgIGN1cnJlbnRVc2VyOiB0aGlzLl9jdXJyZW50VXNlcj8udG9KU09OKClcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgX3NldFJlZGlyZWN0VXNlcihcbiAgICB1c2VyOiBVc2VySW50ZXJuYWwgfCBudWxsLFxuICAgIHBvcHVwUmVkaXJlY3RSZXNvbHZlcj86IFBvcHVwUmVkaXJlY3RSZXNvbHZlclxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZWRpcmVjdE1hbmFnZXIgPSBhd2FpdCB0aGlzLmdldE9ySW5pdFJlZGlyZWN0UGVyc2lzdGVuY2VNYW5hZ2VyKFxuICAgICAgcG9wdXBSZWRpcmVjdFJlc29sdmVyXG4gICAgKTtcbiAgICByZXR1cm4gdXNlciA9PT0gbnVsbFxuICAgICAgPyByZWRpcmVjdE1hbmFnZXIucmVtb3ZlQ3VycmVudFVzZXIoKVxuICAgICAgOiByZWRpcmVjdE1hbmFnZXIuc2V0Q3VycmVudFVzZXIodXNlcik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldE9ySW5pdFJlZGlyZWN0UGVyc2lzdGVuY2VNYW5hZ2VyKFxuICAgIHBvcHVwUmVkaXJlY3RSZXNvbHZlcj86IFBvcHVwUmVkaXJlY3RSZXNvbHZlclxuICApOiBQcm9taXNlPFBlcnNpc3RlbmNlVXNlck1hbmFnZXI+IHtcbiAgICBpZiAoIXRoaXMucmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIpIHtcbiAgICAgIGNvbnN0IHJlc29sdmVyOiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJJbnRlcm5hbCB8IG51bGwgPVxuICAgICAgICAocG9wdXBSZWRpcmVjdFJlc29sdmVyICYmIF9nZXRJbnN0YW5jZShwb3B1cFJlZGlyZWN0UmVzb2x2ZXIpKSB8fFxuICAgICAgICB0aGlzLl9wb3B1cFJlZGlyZWN0UmVzb2x2ZXI7XG4gICAgICBfYXNzZXJ0KHJlc29sdmVyLCB0aGlzLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICAgIHRoaXMucmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIgPSBhd2FpdCBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyLmNyZWF0ZShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgW19nZXRJbnN0YW5jZShyZXNvbHZlci5fcmVkaXJlY3RQZXJzaXN0ZW5jZSldLFxuICAgICAgICBLZXlOYW1lLlJFRElSRUNUX1VTRVJcbiAgICAgICk7XG4gICAgICB0aGlzLnJlZGlyZWN0VXNlciA9XG4gICAgICAgIGF3YWl0IHRoaXMucmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5yZWRpcmVjdFBlcnNpc3RlbmNlTWFuYWdlcjtcbiAgfVxuXG4gIGFzeW5jIF9yZWRpcmVjdFVzZXJGb3JJZChpZDogc3RyaW5nKTogUHJvbWlzZTxVc2VySW50ZXJuYWwgfCBudWxsPiB7XG4gICAgLy8gTWFrZSBzdXJlIHdlJ3ZlIGNsZWFyZWQgYW55IHBlbmRpbmcgcGVyc2lzdGVuY2UgYWN0aW9ucyBpZiB3ZSdyZSBub3QgaW5cbiAgICAvLyB0aGUgaW5pdGlhbGl6ZXJcbiAgICBpZiAodGhpcy5faXNJbml0aWFsaXplZCkge1xuICAgICAgYXdhaXQgdGhpcy5xdWV1ZShhc3luYyAoKSA9PiB7fSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2N1cnJlbnRVc2VyPy5fcmVkaXJlY3RFdmVudElkID09PSBpZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRVc2VyO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnJlZGlyZWN0VXNlcj8uX3JlZGlyZWN0RXZlbnRJZCA9PT0gaWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlZGlyZWN0VXNlcjtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIF9wZXJzaXN0VXNlcklmQ3VycmVudCh1c2VyOiBVc2VySW50ZXJuYWwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodXNlciA9PT0gdGhpcy5jdXJyZW50VXNlcikge1xuICAgICAgcmV0dXJuIHRoaXMucXVldWUoYXN5bmMgKCkgPT4gdGhpcy5kaXJlY3RseVNldEN1cnJlbnRVc2VyKHVzZXIpKTtcbiAgICB9XG4gIH1cblxuICAvKiogTm90aWZpZXMgbGlzdGVuZXJzIG9ubHkgaWYgdGhlIHVzZXIgaXMgY3VycmVudCAqL1xuICBfbm90aWZ5TGlzdGVuZXJzSWZDdXJyZW50KHVzZXI6IFVzZXJJbnRlcm5hbCk6IHZvaWQge1xuICAgIGlmICh1c2VyID09PSB0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICB0aGlzLm5vdGlmeUF1dGhMaXN0ZW5lcnMoKTtcbiAgICB9XG4gIH1cblxuICBfa2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuY29uZmlnLmF1dGhEb21haW59OiR7dGhpcy5jb25maWcuYXBpS2V5fToke3RoaXMubmFtZX1gO1xuICB9XG5cbiAgX3N0YXJ0UHJvYWN0aXZlUmVmcmVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLmlzUHJvYWN0aXZlUmVmcmVzaEVuYWJsZWQgPSB0cnVlO1xuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICB0aGlzLl9jdXJyZW50VXNlci5fc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfVxuICB9XG5cbiAgX3N0b3BQcm9hY3RpdmVSZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMuaXNQcm9hY3RpdmVSZWZyZXNoRW5hYmxlZCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICB0aGlzLl9jdXJyZW50VXNlci5fc3RvcFByb2FjdGl2ZVJlZnJlc2goKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmV0dXJucyB0aGUgY3VycmVudCB1c2VyIGNhc3QgYXMgdGhlIGludGVybmFsIHR5cGUgKi9cbiAgZ2V0IF9jdXJyZW50VXNlcigpOiBVc2VySW50ZXJuYWwge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRVc2VyIGFzIFVzZXJJbnRlcm5hbDtcbiAgfVxuXG4gIHByaXZhdGUgbm90aWZ5QXV0aExpc3RlbmVycygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX2lzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlkVG9rZW5TdWJzY3JpcHRpb24ubmV4dCh0aGlzLmN1cnJlbnRVc2VyKTtcblxuICAgIGNvbnN0IGN1cnJlbnRVaWQgPSB0aGlzLmN1cnJlbnRVc2VyPy51aWQgPz8gbnVsbDtcbiAgICBpZiAodGhpcy5sYXN0Tm90aWZpZWRVaWQgIT09IGN1cnJlbnRVaWQpIHtcbiAgICAgIHRoaXMubGFzdE5vdGlmaWVkVWlkID0gY3VycmVudFVpZDtcbiAgICAgIHRoaXMuYXV0aFN0YXRlU3Vic2NyaXB0aW9uLm5leHQodGhpcy5jdXJyZW50VXNlcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlclN0YXRlTGlzdGVuZXIoXG4gICAgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb248VXNlcj4sXG4gICAgbmV4dE9yT2JzZXJ2ZXI6IE5leHRPck9ic2VydmVyPFVzZXI+LFxuICAgIGVycm9yPzogRXJyb3JGbixcbiAgICBjb21wbGV0ZWQ/OiBDb21wbGV0ZUZuXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICBpZiAodGhpcy5fZGVsZXRlZCkge1xuICAgICAgcmV0dXJuICgpID0+IHt9O1xuICAgIH1cblxuICAgIGNvbnN0IGNiID1cbiAgICAgIHR5cGVvZiBuZXh0T3JPYnNlcnZlciA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICA/IG5leHRPck9ic2VydmVyXG4gICAgICAgIDogbmV4dE9yT2JzZXJ2ZXIubmV4dC5iaW5kKG5leHRPck9ic2VydmVyKTtcblxuICAgIGxldCBpc1Vuc3Vic2NyaWJlZCA9IGZhbHNlO1xuXG4gICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2lzSW5pdGlhbGl6ZWRcbiAgICAgID8gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIDogdGhpcy5faW5pdGlhbGl6YXRpb25Qcm9taXNlO1xuICAgIF9hc3NlcnQocHJvbWlzZSwgdGhpcywgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgLy8gVGhlIGNhbGxiYWNrIG5lZWRzIHRvIGJlIGNhbGxlZCBhc3luY2hyb25vdXNseSBwZXIgdGhlIHNwZWMuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICAgIHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICBpZiAoaXNVbnN1YnNjcmliZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY2IodGhpcy5jdXJyZW50VXNlcik7XG4gICAgfSk7XG5cbiAgICBpZiAodHlwZW9mIG5leHRPck9ic2VydmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjb25zdCB1bnN1YnNjcmliZSA9IHN1YnNjcmlwdGlvbi5hZGRPYnNlcnZlcihcbiAgICAgICAgbmV4dE9yT2JzZXJ2ZXIsXG4gICAgICAgIGVycm9yLFxuICAgICAgICBjb21wbGV0ZWRcbiAgICAgICk7XG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpc1Vuc3Vic2NyaWJlZCA9IHRydWU7XG4gICAgICAgIHVuc3Vic2NyaWJlKCk7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB1bnN1YnNjcmliZSA9IHN1YnNjcmlwdGlvbi5hZGRPYnNlcnZlcihuZXh0T3JPYnNlcnZlcik7XG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpc1Vuc3Vic2NyaWJlZCA9IHRydWU7XG4gICAgICAgIHVuc3Vic2NyaWJlKCk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbnByb3RlY3RlZCAoZnJvbSByYWNlIGNvbmRpdGlvbnMpIG1ldGhvZCB0byBzZXQgdGhlIGN1cnJlbnQgdXNlci4gVGhpc1xuICAgKiBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSB3aXRoaW4gYSBxdWV1ZWQgY2FsbGJhY2suIFRoaXMgaXMgbmVjZXNzYXJ5XG4gICAqIGJlY2F1c2UgdGhlIHF1ZXVlIHNob3VsZG4ndCByZWx5IG9uIGFub3RoZXIgcXVldWVkIGNhbGxiYWNrLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBkaXJlY3RseVNldEN1cnJlbnRVc2VyKFxuICAgIHVzZXI6IFVzZXJJbnRlcm5hbCB8IG51bGxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY3VycmVudFVzZXIgJiYgdGhpcy5jdXJyZW50VXNlciAhPT0gdXNlcikge1xuICAgICAgdGhpcy5fY3VycmVudFVzZXIuX3N0b3BQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfVxuICAgIGlmICh1c2VyICYmIHRoaXMuaXNQcm9hY3RpdmVSZWZyZXNoRW5hYmxlZCkge1xuICAgICAgdXNlci5fc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50VXNlciA9IHVzZXI7XG5cbiAgICBpZiAodXNlcikge1xuICAgICAgYXdhaXQgdGhpcy5hc3NlcnRlZFBlcnNpc3RlbmNlLnNldEN1cnJlbnRVc2VyKHVzZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2UucmVtb3ZlQ3VycmVudFVzZXIoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHF1ZXVlKGFjdGlvbjogQXN5bmNBY3Rpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBJbiBjYXNlIHNvbWV0aGluZyBlcnJvcnMsIHRoZSBjYWxsYmFjayBzdGlsbCBzaG91bGQgYmUgY2FsbGVkIGluIG9yZGVyXG4gICAgLy8gdG8ga2VlcCB0aGUgcHJvbWlzZSBjaGFpbiBhbGl2ZVxuICAgIHRoaXMub3BlcmF0aW9ucyA9IHRoaXMub3BlcmF0aW9ucy50aGVuKGFjdGlvbiwgYWN0aW9uKTtcbiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgYXNzZXJ0ZWRQZXJzaXN0ZW5jZSgpOiBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyIHtcbiAgICBfYXNzZXJ0KHRoaXMucGVyc2lzdGVuY2VNYW5hZ2VyLCB0aGlzLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICByZXR1cm4gdGhpcy5wZXJzaXN0ZW5jZU1hbmFnZXI7XG4gIH1cblxuICBwcml2YXRlIGZyYW1ld29ya3M6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgY2xpZW50VmVyc2lvbjogc3RyaW5nO1xuICBfbG9nRnJhbWV3b3JrKGZyYW1ld29yazogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFmcmFtZXdvcmsgfHwgdGhpcy5mcmFtZXdvcmtzLmluY2x1ZGVzKGZyYW1ld29yaykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5mcmFtZXdvcmtzLnB1c2goZnJhbWV3b3JrKTtcblxuICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgc28gdGhhdCBcIkZpcmViYXNlQ29yZS13ZWIsRmlyZWJhc2VVSS13ZWJcIiBhbmRcbiAgICAvLyBcIkZpcmViYXNlVUktd2ViLEZpcmViYXNlQ29yZS13ZWJcIiBhcmVuJ3Qgdmlld2VkIGFzIGRpZmZlcmVudC5cbiAgICB0aGlzLmZyYW1ld29ya3Muc29ydCgpO1xuICAgIHRoaXMuY2xpZW50VmVyc2lvbiA9IF9nZXRDbGllbnRWZXJzaW9uKFxuICAgICAgdGhpcy5jb25maWcuY2xpZW50UGxhdGZvcm0sXG4gICAgICB0aGlzLl9nZXRGcmFtZXdvcmtzKClcbiAgICApO1xuICB9XG4gIF9nZXRGcmFtZXdvcmtzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5mcmFtZXdvcmtzO1xuICB9XG4gIGFzeW5jIF9nZXRBZGRpdGlvbmFsSGVhZGVycygpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgICAvLyBBZGRpdGlvbmFsIGhlYWRlcnMgb24gZXZlcnkgcmVxdWVzdFxuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBbSHR0cEhlYWRlci5YX0NMSUVOVF9WRVJTSU9OXTogdGhpcy5jbGllbnRWZXJzaW9uXG4gICAgfTtcblxuICAgIGlmICh0aGlzLmFwcC5vcHRpb25zLmFwcElkKSB7XG4gICAgICBoZWFkZXJzW0h0dHBIZWFkZXIuWF9GSVJFQkFTRV9HTVBJRF0gPSB0aGlzLmFwcC5vcHRpb25zLmFwcElkO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBoZWFydGJlYXQgc2VydmljZSBleGlzdHMsIGFkZCB0aGUgaGVhcnRiZWF0IHN0cmluZ1xuICAgIGNvbnN0IGhlYXJ0YmVhdHNIZWFkZXIgPSBhd2FpdCB0aGlzLmhlYXJ0YmVhdFNlcnZpY2VQcm92aWRlclxuICAgICAgLmdldEltbWVkaWF0ZSh7XG4gICAgICAgIG9wdGlvbmFsOiB0cnVlXG4gICAgICB9KVxuICAgICAgPy5nZXRIZWFydGJlYXRzSGVhZGVyKCk7XG4gICAgaWYgKGhlYXJ0YmVhdHNIZWFkZXIpIHtcbiAgICAgIGhlYWRlcnNbSHR0cEhlYWRlci5YX0ZJUkVCQVNFX0NMSUVOVF0gPSBoZWFydGJlYXRzSGVhZGVyO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBBcHAgQ2hlY2sgc2VydmljZSBleGlzdHMsIGFkZCB0aGUgQXBwIENoZWNrIHRva2VuIGluIHRoZSBoZWFkZXJzXG4gICAgY29uc3QgYXBwQ2hlY2tUb2tlbiA9IGF3YWl0IHRoaXMuX2dldEFwcENoZWNrVG9rZW4oKTtcbiAgICBpZiAoYXBwQ2hlY2tUb2tlbikge1xuICAgICAgaGVhZGVyc1tIdHRwSGVhZGVyLlhfRklSRUJBU0VfQVBQX0NIRUNLXSA9IGFwcENoZWNrVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cblxuICBhc3luYyBfZ2V0QXBwQ2hlY2tUb2tlbigpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmFwcCkgJiYgdGhpcy5hcHAuc2V0dGluZ3MuYXBwQ2hlY2tUb2tlbikge1xuICAgICAgcmV0dXJuIHRoaXMuYXBwLnNldHRpbmdzLmFwcENoZWNrVG9rZW47XG4gICAgfVxuICAgIGNvbnN0IGFwcENoZWNrVG9rZW5SZXN1bHQgPSBhd2FpdCB0aGlzLmFwcENoZWNrU2VydmljZVByb3ZpZGVyXG4gICAgICAuZ2V0SW1tZWRpYXRlKHsgb3B0aW9uYWw6IHRydWUgfSlcbiAgICAgID8uZ2V0VG9rZW4oKTtcbiAgICBpZiAoYXBwQ2hlY2tUb2tlblJlc3VsdD8uZXJyb3IpIHtcbiAgICAgIC8vIENvbnRleHQ6IGFwcENoZWNrLmdldFRva2VuKCkgd2lsbCBuZXZlciB0aHJvdyBldmVuIGlmIGFuIGVycm9yIGhhcHBlbmVkLlxuICAgICAgLy8gSW4gdGhlIGVycm9yIGNhc2UsIGEgZHVtbXkgdG9rZW4gd2lsbCBiZSByZXR1cm5lZCBhbG9uZyB3aXRoIGFuIGVycm9yIGZpZWxkIGRlc2NyaWJpbmdcbiAgICAgIC8vIHRoZSBlcnJvci4gSW4gZ2VuZXJhbCwgd2Ugc2hvdWxkbid0IGNhcmUgYWJvdXQgdGhlIGVycm9yIGNvbmRpdGlvbiBhbmQganVzdCB1c2VcbiAgICAgIC8vIHRoZSB0b2tlbiAoYWN0dWFsIG9yIGR1bW15KSB0byBzZW5kIHJlcXVlc3RzLlxuICAgICAgX2xvZ1dhcm4oXG4gICAgICAgIGBFcnJvciB3aGlsZSByZXRyaWV2aW5nIEFwcCBDaGVjayB0b2tlbjogJHthcHBDaGVja1Rva2VuUmVzdWx0LmVycm9yfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBhcHBDaGVja1Rva2VuUmVzdWx0Py50b2tlbjtcbiAgfVxufVxuXG4vKipcbiAqIE1ldGhvZCB0byBiZSB1c2VkIHRvIGNhc3QgZG93biB0byBvdXIgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBvZiBBdXRoLlxuICogSXQgd2lsbCBhbHNvIGhhbmRsZSB1bndyYXBwaW5nIGZyb20gdGhlIGNvbXBhdCB0eXBlIGlmIG5lY2Vzc2FyeVxuICpcbiAqIEBwYXJhbSBhdXRoIEF1dGggb2JqZWN0IHBhc3NlZCBpbiBmcm9tIGRldmVsb3BlclxuICovXG5leHBvcnQgZnVuY3Rpb24gX2Nhc3RBdXRoKGF1dGg6IEF1dGgpOiBBdXRoSW50ZXJuYWwge1xuICByZXR1cm4gZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpIGFzIEF1dGhJbnRlcm5hbDtcbn1cblxuLyoqIEhlbHBlciBjbGFzcyB0byB3cmFwIHN1YnNjcmliZXIgbG9naWMgKi9cbmNsYXNzIFN1YnNjcmlwdGlvbjxUPiB7XG4gIHByaXZhdGUgb2JzZXJ2ZXI6IE9ic2VydmVyPFQgfCBudWxsPiB8IG51bGwgPSBudWxsO1xuICByZWFkb25seSBhZGRPYnNlcnZlcjogU3Vic2NyaWJlPFQgfCBudWxsPiA9IGNyZWF0ZVN1YnNjcmliZShcbiAgICBvYnNlcnZlciA9PiAodGhpcy5vYnNlcnZlciA9IG9ic2VydmVyKVxuICApO1xuXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbCkge31cblxuICBnZXQgbmV4dCgpOiBOZXh0Rm48VCB8IG51bGw+IHtcbiAgICBfYXNzZXJ0KHRoaXMub2JzZXJ2ZXIsIHRoaXMuYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgcmV0dXJuIHRoaXMub2JzZXJ2ZXIubmV4dC5iaW5kKHRoaXMub2JzZXJ2ZXIpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW50ZXJmYWNlIEV4dGVybmFsSlNQcm92aWRlciB7XG4gIGxvYWRKUyh1cmw6IHN0cmluZyk6IFByb21pc2U8RXZlbnQ+O1xuICByZWNhcHRjaGFWMlNjcmlwdDogc3RyaW5nO1xuICByZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0OiBzdHJpbmc7XG4gIGdhcGlTY3JpcHQ6IHN0cmluZztcbn1cblxubGV0IGV4dGVybmFsSlNQcm92aWRlcjogRXh0ZXJuYWxKU1Byb3ZpZGVyID0ge1xuICBhc3luYyBsb2FkSlMoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gbG9hZCBleHRlcm5hbCBzY3JpcHRzJyk7XG4gIH0sXG5cbiAgcmVjYXB0Y2hhVjJTY3JpcHQ6ICcnLFxuICByZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0OiAnJyxcbiAgZ2FwaVNjcmlwdDogJydcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBfc2V0RXh0ZXJuYWxKU1Byb3ZpZGVyKHA6IEV4dGVybmFsSlNQcm92aWRlcik6IHZvaWQge1xuICBleHRlcm5hbEpTUHJvdmlkZXIgPSBwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2xvYWRKUyh1cmw6IHN0cmluZyk6IFByb21pc2U8RXZlbnQ+IHtcbiAgcmV0dXJuIGV4dGVybmFsSlNQcm92aWRlci5sb2FkSlModXJsKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9yZWNhcHRjaGFWMlNjcmlwdFVybCgpOiBzdHJpbmcge1xuICByZXR1cm4gZXh0ZXJuYWxKU1Byb3ZpZGVyLnJlY2FwdGNoYVYyU2NyaXB0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3JlY2FwdGNoYUVudGVycHJpc2VTY3JpcHRVcmwoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGV4dGVybmFsSlNQcm92aWRlci5yZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2dhcGlTY3JpcHRVcmwoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGV4dGVybmFsSlNQcm92aWRlci5nYXBpU2NyaXB0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2dlbmVyYXRlQ2FsbGJhY2tOYW1lKHByZWZpeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBfXyR7cHJlZml4fSR7TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDAwMCl9YDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBSZWNhcHRjaGFQYXJhbWV0ZXJzIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7XG4gIFJlY2FwdGNoYSxcbiAgR3JlQ0FQVENIQVRvcExldmVsLFxuICBHcmVDQVBUQ0hBUmVuZGVyT3B0aW9uLFxuICBHcmVDQVBUQ0hBXG59IGZyb20gJy4vcmVjYXB0Y2hhJztcblxuZXhwb3J0IGNvbnN0IF9TT0xWRV9USU1FX01TID0gNTAwO1xuZXhwb3J0IGNvbnN0IF9FWFBJUkFUSU9OX1RJTUVfTVMgPSA2MF8wMDA7XG5leHBvcnQgY29uc3QgX1dJREdFVF9JRF9TVEFSVCA9IDFfMDAwXzAwMF8wMDBfMDAwO1xuXG5leHBvcnQgaW50ZXJmYWNlIFdpZGdldCB7XG4gIGdldFJlc3BvbnNlOiAoKSA9PiBzdHJpbmcgfCBudWxsO1xuICBkZWxldGU6ICgpID0+IHZvaWQ7XG4gIGV4ZWN1dGU6ICgpID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBNb2NrUmVDYXB0Y2hhIGltcGxlbWVudHMgUmVjYXB0Y2hhIHtcbiAgcHJpdmF0ZSBjb3VudGVyID0gX1dJREdFVF9JRF9TVEFSVDtcbiAgX3dpZGdldHMgPSBuZXcgTWFwPG51bWJlciwgV2lkZ2V0PigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgYXV0aDogQXV0aEludGVybmFsKSB7fVxuXG4gIHJlbmRlcihcbiAgICBjb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIHBhcmFtZXRlcnM/OiBSZWNhcHRjaGFQYXJhbWV0ZXJzXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgaWQgPSB0aGlzLmNvdW50ZXI7XG4gICAgdGhpcy5fd2lkZ2V0cy5zZXQoXG4gICAgICBpZCxcbiAgICAgIG5ldyBNb2NrV2lkZ2V0KGNvbnRhaW5lciwgdGhpcy5hdXRoLm5hbWUsIHBhcmFtZXRlcnMgfHwge30pXG4gICAgKTtcbiAgICB0aGlzLmNvdW50ZXIrKztcbiAgICByZXR1cm4gaWQ7XG4gIH1cblxuICByZXNldChvcHRXaWRnZXRJZD86IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGlkID0gb3B0V2lkZ2V0SWQgfHwgX1dJREdFVF9JRF9TVEFSVDtcbiAgICB2b2lkIHRoaXMuX3dpZGdldHMuZ2V0KGlkKT8uZGVsZXRlKCk7XG4gICAgdGhpcy5fd2lkZ2V0cy5kZWxldGUoaWQpO1xuICB9XG5cbiAgZ2V0UmVzcG9uc2Uob3B0V2lkZ2V0SWQ/OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGlkID0gb3B0V2lkZ2V0SWQgfHwgX1dJREdFVF9JRF9TVEFSVDtcbiAgICByZXR1cm4gdGhpcy5fd2lkZ2V0cy5nZXQoaWQpPy5nZXRSZXNwb25zZSgpIHx8ICcnO1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZShvcHRXaWRnZXRJZD86IG51bWJlciB8IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgaWQ6IG51bWJlciA9IChvcHRXaWRnZXRJZCBhcyBudW1iZXIpIHx8IF9XSURHRVRfSURfU1RBUlQ7XG4gICAgdm9pZCB0aGlzLl93aWRnZXRzLmdldChpZCk/LmV4ZWN1dGUoKTtcbiAgICByZXR1cm4gJyc7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1vY2tHcmVDQVBUQ0hBVG9wTGV2ZWwgaW1wbGVtZW50cyBHcmVDQVBUQ0hBVG9wTGV2ZWwge1xuICBlbnRlcnByaXNlOiBHcmVDQVBUQ0hBID0gbmV3IE1vY2tHcmVDQVBUQ0hBKCk7XG4gIHJlYWR5KGNhbGxiYWNrOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGV4ZWN1dGUoXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIF9zaXRlS2V5OiBzdHJpbmcsXG4gICAgX29wdGlvbnM6IHsgYWN0aW9uOiBzdHJpbmcgfVxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoJ3Rva2VuJyk7XG4gIH1cbiAgcmVuZGVyKFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBfY29udGFpbmVyOiBzdHJpbmcgfCBIVE1MRWxlbWVudCxcbiAgICBfcGFyYW1ldGVyczogR3JlQ0FQVENIQVJlbmRlck9wdGlvblxuICApOiBzdHJpbmcge1xuICAgIHJldHVybiAnJztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTW9ja0dyZUNBUFRDSEEgaW1wbGVtZW50cyBHcmVDQVBUQ0hBIHtcbiAgcmVhZHkoY2FsbGJhY2s6ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgZXhlY3V0ZShcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgX3NpdGVLZXk6IHN0cmluZyxcbiAgICBfb3B0aW9uczogeyBhY3Rpb246IHN0cmluZyB9XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgndG9rZW4nKTtcbiAgfVxuICByZW5kZXIoXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIF9jb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIF9wYXJhbWV0ZXJzOiBHcmVDQVBUQ0hBUmVuZGVyT3B0aW9uXG4gICk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNb2NrV2lkZ2V0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXI6IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGlzVmlzaWJsZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSB0aW1lcklkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBkZWxldGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcmVzcG9uc2VUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2xpY2tIYW5kbGVyID0gKCk6IHZvaWQgPT4ge1xuICAgIHRoaXMuZXhlY3V0ZSgpO1xuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNvbnRhaW5lck9ySWQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIGFwcE5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBhcmFtczogUmVjYXB0Y2hhUGFyYW1ldGVyc1xuICApIHtcbiAgICBjb25zdCBjb250YWluZXIgPVxuICAgICAgdHlwZW9mIGNvbnRhaW5lck9ySWQgPT09ICdzdHJpbmcnXG4gICAgICAgID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY29udGFpbmVyT3JJZClcbiAgICAgICAgOiBjb250YWluZXJPcklkO1xuICAgIF9hc3NlcnQoY29udGFpbmVyLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SLCB7IGFwcE5hbWUgfSk7XG5cbiAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICB0aGlzLmlzVmlzaWJsZSA9IHRoaXMucGFyYW1zLnNpemUgIT09ICdpbnZpc2libGUnO1xuICAgIGlmICh0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgdGhpcy5leGVjdXRlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5jbGlja0hhbmRsZXIpO1xuICAgIH1cbiAgfVxuXG4gIGdldFJlc3BvbnNlKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHRoaXMuY2hlY2tJZkRlbGV0ZWQoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZVRva2VuO1xuICB9XG5cbiAgZGVsZXRlKCk6IHZvaWQge1xuICAgIHRoaXMuY2hlY2tJZkRlbGV0ZWQoKTtcbiAgICB0aGlzLmRlbGV0ZWQgPSB0cnVlO1xuICAgIGlmICh0aGlzLnRpbWVySWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVySWQpO1xuICAgICAgdGhpcy50aW1lcklkID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5jb250YWluZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmNsaWNrSGFuZGxlcik7XG4gIH1cblxuICBleGVjdXRlKCk6IHZvaWQge1xuICAgIHRoaXMuY2hlY2tJZkRlbGV0ZWQoKTtcbiAgICBpZiAodGhpcy50aW1lcklkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy50aW1lcklkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5yZXNwb25zZVRva2VuID0gZ2VuZXJhdGVSYW5kb21BbHBoYU51bWVyaWNTdHJpbmcoNTApO1xuICAgICAgY29uc3QgeyBjYWxsYmFjaywgJ2V4cGlyZWQtY2FsbGJhY2snOiBleHBpcmVkQ2FsbGJhY2sgfSA9IHRoaXMucGFyYW1zO1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY2FsbGJhY2sodGhpcy5yZXNwb25zZVRva2VuKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgIH1cblxuICAgICAgdGhpcy50aW1lcklkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnRpbWVySWQgPSBudWxsO1xuICAgICAgICB0aGlzLnJlc3BvbnNlVG9rZW4gPSBudWxsO1xuICAgICAgICBpZiAoZXhwaXJlZENhbGxiYWNrKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGV4cGlyZWRDYWxsYmFjaygpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgICB0aGlzLmV4ZWN1dGUoKTtcbiAgICAgICAgfVxuICAgICAgfSwgX0VYUElSQVRJT05fVElNRV9NUyk7XG4gICAgfSwgX1NPTFZFX1RJTUVfTVMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0lmRGVsZXRlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kZWxldGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlQ0FQVENIQSBtb2NrIHdhcyBhbHJlYWR5IGRlbGV0ZWQhJyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlUmFuZG9tQWxwaGFOdW1lcmljU3RyaW5nKGxlbjogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgY2hhcnMgPSBbXTtcbiAgY29uc3QgYWxsb3dlZENoYXJzID1cbiAgICAnMTIzNDU2Nzg5MGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVonO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgY2hhcnMucHVzaChcbiAgICAgIGFsbG93ZWRDaGFycy5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYWxsb3dlZENoYXJzLmxlbmd0aCkpXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY2hhcnMuam9pbignJyk7XG59XG4iLCAiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgaXNFbnRlcnByaXNlLCBSZWNhcHRjaGFDb25maWcgfSBmcm9tICcuL3JlY2FwdGNoYSc7XG5pbXBvcnQgeyBnZXRSZWNhcHRjaGFDb25maWcgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vcmVjYXB0Y2hhJztcbmltcG9ydCB7XG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYVZlcnNpb24sXG4gIFJlY2FwdGNoYUFjdGlvbk5hbWUsXG4gIFJlY2FwdGNoYUF1dGhQcm92aWRlcixcbiAgRW5mb3JjZW1lbnRTdGF0ZVxufSBmcm9tICcuLi8uLi9hcGknO1xuXG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgKiBhcyBqc0hlbHBlcnMgZnJvbSAnLi4vbG9hZF9qcyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgU3RhcnRQaG9uZU1mYUVucm9sbG1lbnRSZXF1ZXN0IH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9tZmEnO1xuaW1wb3J0IHsgU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3QgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IE1vY2tHcmVDQVBUQ0hBVG9wTGV2ZWwgfSBmcm9tICcuL3JlY2FwdGNoYV9tb2NrJztcblxuZXhwb3J0IGNvbnN0IFJFQ0FQVENIQV9FTlRFUlBSSVNFX1ZFUklGSUVSX1RZUEUgPSAncmVjYXB0Y2hhLWVudGVycHJpc2UnO1xuZXhwb3J0IGNvbnN0IEZBS0VfVE9LRU4gPSAnTk9fUkVDQVBUQ0hBJztcblxuZXhwb3J0IGNsYXNzIFJlY2FwdGNoYUVudGVycHJpc2VWZXJpZmllciB7XG4gIC8qKlxuICAgKiBJZGVudGlmaWVzIHRoZSB0eXBlIG9mIGFwcGxpY2F0aW9uIHZlcmlmaWVyIChlLmcuIFwicmVjYXB0Y2hhLWVudGVycHJpc2VcIikuXG4gICAqL1xuICByZWFkb25seSB0eXBlID0gUkVDQVBUQ0hBX0VOVEVSUFJJU0VfVkVSSUZJRVJfVFlQRTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbDtcblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGF1dGhFeHRlcm4gLSBUaGUgY29ycmVzcG9uZGluZyBGaXJlYmFzZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gICAqXG4gICAqL1xuICBjb25zdHJ1Y3RvcihhdXRoRXh0ZXJuOiBBdXRoKSB7XG4gICAgdGhpcy5hdXRoID0gX2Nhc3RBdXRoKGF1dGhFeHRlcm4pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGVzIHRoZSB2ZXJpZmljYXRpb24gcHJvY2Vzcy5cbiAgICpcbiAgICogQHJldHVybnMgQSBQcm9taXNlIGZvciBhIHRva2VuIHRoYXQgY2FuIGJlIHVzZWQgdG8gYXNzZXJ0IHRoZSB2YWxpZGl0eSBvZiBhIHJlcXVlc3QuXG4gICAqL1xuICBhc3luYyB2ZXJpZnkoXG4gICAgYWN0aW9uOiBzdHJpbmcgPSAndmVyaWZ5JyxcbiAgICBmb3JjZVJlZnJlc2ggPSBmYWxzZVxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGFzeW5jIGZ1bmN0aW9uIHJldHJpZXZlU2l0ZUtleShhdXRoOiBBdXRoSW50ZXJuYWwpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgaWYgKCFmb3JjZVJlZnJlc2gpIHtcbiAgICAgICAgaWYgKGF1dGgudGVuYW50SWQgPT0gbnVsbCAmJiBhdXRoLl9hZ2VudFJlY2FwdGNoYUNvbmZpZyAhPSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGF1dGguX2FnZW50UmVjYXB0Y2hhQ29uZmlnLnNpdGVLZXk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGF1dGgudGVuYW50SWQgIT0gbnVsbCAmJlxuICAgICAgICAgIGF1dGguX3RlbmFudFJlY2FwdGNoYUNvbmZpZ3NbYXV0aC50ZW5hbnRJZF0gIT09IHVuZGVmaW5lZFxuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gYXV0aC5fdGVuYW50UmVjYXB0Y2hhQ29uZmlnc1thdXRoLnRlbmFudElkXS5zaXRlS2V5O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxzdHJpbmc+KGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZ2V0UmVjYXB0Y2hhQ29uZmlnKGF1dGgsIHtcbiAgICAgICAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQixcbiAgICAgICAgICB2ZXJzaW9uOiBSZWNhcHRjaGFWZXJzaW9uLkVOVEVSUFJJU0VcbiAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UucmVjYXB0Y2hhS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcigncmVjYXB0Y2hhIEVudGVycHJpc2Ugc2l0ZSBrZXkgdW5kZWZpbmVkJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29uc3QgY29uZmlnID0gbmV3IFJlY2FwdGNoYUNvbmZpZyhyZXNwb25zZSk7XG4gICAgICAgICAgICAgIGlmIChhdXRoLnRlbmFudElkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhdXRoLl9hZ2VudFJlY2FwdGNoYUNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhdXRoLl90ZW5hbnRSZWNhcHRjaGFDb25maWdzW2F1dGgudGVuYW50SWRdID0gY29uZmlnO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGNvbmZpZy5zaXRlS2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmV0cmlldmVSZWNhcHRjaGFUb2tlbihcbiAgICAgIHNpdGVLZXk6IHN0cmluZyxcbiAgICAgIHJlc29sdmU6ICh2YWx1ZTogc3RyaW5nIHwgUHJvbWlzZUxpa2U8c3RyaW5nPikgPT4gdm9pZCxcbiAgICAgIHJlamVjdDogKHJlYXNvbj86IHVua25vd24pID0+IHZvaWRcbiAgICApOiB2b2lkIHtcbiAgICAgIGNvbnN0IGdyZWNhcHRjaGEgPSB3aW5kb3cuZ3JlY2FwdGNoYTtcbiAgICAgIGlmIChpc0VudGVycHJpc2UoZ3JlY2FwdGNoYSkpIHtcbiAgICAgICAgZ3JlY2FwdGNoYS5lbnRlcnByaXNlLnJlYWR5KCgpID0+IHtcbiAgICAgICAgICBncmVjYXB0Y2hhLmVudGVycHJpc2VcbiAgICAgICAgICAgIC5leGVjdXRlKHNpdGVLZXksIHsgYWN0aW9uIH0pXG4gICAgICAgICAgICAudGhlbih0b2tlbiA9PiB7XG4gICAgICAgICAgICAgIHJlc29sdmUodG9rZW4pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAgIHJlc29sdmUoRkFLRV9UT0tFTik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWplY3QoRXJyb3IoJ05vIHJlQ0FQVENIQSBlbnRlcnByaXNlIHNjcmlwdCBsb2FkZWQuJykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybnMgUHJvbWlzZSBmb3IgYSBtb2NrIHRva2VuIHdoZW4gYXBwVmVyaWZpY2F0aW9uRGlzYWJsZWRGb3JUZXN0aW5nIGlzIHRydWUuXG4gICAgaWYgKHRoaXMuYXV0aC5zZXR0aW5ncy5hcHBWZXJpZmljYXRpb25EaXNhYmxlZEZvclRlc3RpbmcpIHtcbiAgICAgIGNvbnN0IG1vY2tSZWNhcHRjaGEgPSBuZXcgTW9ja0dyZUNBUFRDSEFUb3BMZXZlbCgpO1xuICAgICAgcmV0dXJuIG1vY2tSZWNhcHRjaGEuZXhlY3V0ZSgnc2l0ZUtleScsIHsgYWN0aW9uOiAndmVyaWZ5JyB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICByZXRyaWV2ZVNpdGVLZXkodGhpcy5hdXRoKVxuICAgICAgICAudGhlbihzaXRlS2V5ID0+IHtcbiAgICAgICAgICBpZiAoIWZvcmNlUmVmcmVzaCAmJiBpc0VudGVycHJpc2Uod2luZG93LmdyZWNhcHRjaGEpKSB7XG4gICAgICAgICAgICByZXRyaWV2ZVJlY2FwdGNoYVRva2VuKHNpdGVLZXksIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKCdSZWNhcHRjaGFWZXJpZmllciBpcyBvbmx5IHN1cHBvcnRlZCBpbiBicm93c2VyJylcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHVybCA9IGpzSGVscGVycy5fcmVjYXB0Y2hhRW50ZXJwcmlzZVNjcmlwdFVybCgpO1xuICAgICAgICAgICAgaWYgKHVybC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgdXJsICs9IHNpdGVLZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBqc0hlbHBlcnNcbiAgICAgICAgICAgICAgLl9sb2FkSlModXJsKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0cmlldmVSZWNhcHRjaGFUb2tlbihzaXRlS2V5LCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5qZWN0UmVjYXB0Y2hhRmllbGRzPFQgZXh0ZW5kcyBvYmplY3Q+KFxuICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFQsXG4gIGFjdGlvbjogUmVjYXB0Y2hhQWN0aW9uTmFtZSxcbiAgaXNDYXB0Y2hhUmVzcCA9IGZhbHNlLFxuICBpc0Zha2VUb2tlbiA9IGZhbHNlXG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgdmVyaWZpZXIgPSBuZXcgUmVjYXB0Y2hhRW50ZXJwcmlzZVZlcmlmaWVyKGF1dGgpO1xuICBsZXQgY2FwdGNoYVJlc3BvbnNlO1xuXG4gIGlmIChpc0Zha2VUb2tlbikge1xuICAgIGNhcHRjaGFSZXNwb25zZSA9IEZBS0VfVE9LRU47XG4gIH0gZWxzZSB7XG4gICAgdHJ5IHtcbiAgICAgIGNhcHRjaGFSZXNwb25zZSA9IGF3YWl0IHZlcmlmaWVyLnZlcmlmeShhY3Rpb24pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjYXB0Y2hhUmVzcG9uc2UgPSBhd2FpdCB2ZXJpZmllci52ZXJpZnkoYWN0aW9uLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBuZXdSZXF1ZXN0ID0geyAuLi5yZXF1ZXN0IH07XG4gIGlmIChcbiAgICBhY3Rpb24gPT09IFJlY2FwdGNoYUFjdGlvbk5hbWUuTUZBX1NNU19FTlJPTExNRU5UIHx8XG4gICAgYWN0aW9uID09PSBSZWNhcHRjaGFBY3Rpb25OYW1lLk1GQV9TTVNfU0lHTklOXG4gICkge1xuICAgIGlmICgncGhvbmVFbnJvbGxtZW50SW5mbycgaW4gbmV3UmVxdWVzdCkge1xuICAgICAgY29uc3QgcGhvbmVOdW1iZXIgPSAoXG4gICAgICAgIG5ld1JlcXVlc3QgYXMgdW5rbm93biBhcyBTdGFydFBob25lTWZhRW5yb2xsbWVudFJlcXVlc3RcbiAgICAgICkucGhvbmVFbnJvbGxtZW50SW5mby5waG9uZU51bWJlcjtcbiAgICAgIGNvbnN0IHJlY2FwdGNoYVRva2VuID0gKFxuICAgICAgICBuZXdSZXF1ZXN0IGFzIHVua25vd24gYXMgU3RhcnRQaG9uZU1mYUVucm9sbG1lbnRSZXF1ZXN0XG4gICAgICApLnBob25lRW5yb2xsbWVudEluZm8ucmVjYXB0Y2hhVG9rZW47XG5cbiAgICAgIE9iamVjdC5hc3NpZ24obmV3UmVxdWVzdCwge1xuICAgICAgICAncGhvbmVFbnJvbGxtZW50SW5mbyc6IHtcbiAgICAgICAgICBwaG9uZU51bWJlcixcbiAgICAgICAgICByZWNhcHRjaGFUb2tlbixcbiAgICAgICAgICBjYXB0Y2hhUmVzcG9uc2UsXG4gICAgICAgICAgJ2NsaWVudFR5cGUnOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQixcbiAgICAgICAgICAncmVjYXB0Y2hhVmVyc2lvbic6IFJlY2FwdGNoYVZlcnNpb24uRU5URVJQUklTRVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKCdwaG9uZVNpZ25JbkluZm8nIGluIG5ld1JlcXVlc3QpIHtcbiAgICAgIGNvbnN0IHJlY2FwdGNoYVRva2VuID0gKFxuICAgICAgICBuZXdSZXF1ZXN0IGFzIHVua25vd24gYXMgU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3RcbiAgICAgICkucGhvbmVTaWduSW5JbmZvLnJlY2FwdGNoYVRva2VuO1xuXG4gICAgICBPYmplY3QuYXNzaWduKG5ld1JlcXVlc3QsIHtcbiAgICAgICAgJ3Bob25lU2lnbkluSW5mbyc6IHtcbiAgICAgICAgICByZWNhcHRjaGFUb2tlbixcbiAgICAgICAgICBjYXB0Y2hhUmVzcG9uc2UsXG4gICAgICAgICAgJ2NsaWVudFR5cGUnOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQixcbiAgICAgICAgICAncmVjYXB0Y2hhVmVyc2lvbic6IFJlY2FwdGNoYVZlcnNpb24uRU5URVJQUklTRVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld1JlcXVlc3Q7XG4gIH1cblxuICBpZiAoIWlzQ2FwdGNoYVJlc3ApIHtcbiAgICBPYmplY3QuYXNzaWduKG5ld1JlcXVlc3QsIHsgY2FwdGNoYVJlc3BvbnNlIH0pO1xuICB9IGVsc2Uge1xuICAgIE9iamVjdC5hc3NpZ24obmV3UmVxdWVzdCwgeyAnY2FwdGNoYVJlc3AnOiBjYXB0Y2hhUmVzcG9uc2UgfSk7XG4gIH1cbiAgT2JqZWN0LmFzc2lnbihuZXdSZXF1ZXN0LCB7ICdjbGllbnRUeXBlJzogUmVjYXB0Y2hhQ2xpZW50VHlwZS5XRUIgfSk7XG4gIE9iamVjdC5hc3NpZ24obmV3UmVxdWVzdCwge1xuICAgICdyZWNhcHRjaGFWZXJzaW9uJzogUmVjYXB0Y2hhVmVyc2lvbi5FTlRFUlBSSVNFXG4gIH0pO1xuICByZXR1cm4gbmV3UmVxdWVzdDtcbn1cblxudHlwZSBBY3Rpb25NZXRob2Q8VFJlcXVlc3QsIFRSZXNwb25zZT4gPSAoXG4gIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgcmVxdWVzdDogVFJlcXVlc3RcbikgPT4gUHJvbWlzZTxUUmVzcG9uc2U+O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmVjYXB0Y2hhRmxvdzxUUmVxdWVzdCBleHRlbmRzIG9iamVjdCwgVFJlc3BvbnNlPihcbiAgYXV0aEluc3RhbmNlOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFRSZXF1ZXN0LFxuICBhY3Rpb25OYW1lOiBSZWNhcHRjaGFBY3Rpb25OYW1lLFxuICBhY3Rpb25NZXRob2Q6IEFjdGlvbk1ldGhvZDxUUmVxdWVzdCwgVFJlc3BvbnNlPixcbiAgcmVjYXB0Y2hhQXV0aFByb3ZpZGVyOiBSZWNhcHRjaGFBdXRoUHJvdmlkZXJcbik6IFByb21pc2U8VFJlc3BvbnNlPiB7XG4gIGlmIChyZWNhcHRjaGFBdXRoUHJvdmlkZXIgPT09IFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUikge1xuICAgIGlmIChcbiAgICAgIGF1dGhJbnN0YW5jZVxuICAgICAgICAuX2dldFJlY2FwdGNoYUNvbmZpZygpXG4gICAgICAgID8uaXNQcm92aWRlckVuYWJsZWQoUmVjYXB0Y2hhQXV0aFByb3ZpZGVyLkVNQUlMX1BBU1NXT1JEX1BST1ZJREVSKVxuICAgICkge1xuICAgICAgY29uc3QgcmVxdWVzdFdpdGhSZWNhcHRjaGEgPSBhd2FpdCBpbmplY3RSZWNhcHRjaGFGaWVsZHMoXG4gICAgICAgIGF1dGhJbnN0YW5jZSxcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgYWN0aW9uTmFtZSxcbiAgICAgICAgYWN0aW9uTmFtZSA9PT0gUmVjYXB0Y2hhQWN0aW9uTmFtZS5HRVRfT09CX0NPREVcbiAgICAgICk7XG4gICAgICByZXR1cm4gYWN0aW9uTWV0aG9kKGF1dGhJbnN0YW5jZSwgcmVxdWVzdFdpdGhSZWNhcHRjaGEpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYWN0aW9uTWV0aG9kKGF1dGhJbnN0YW5jZSwgcmVxdWVzdCkuY2F0Y2goYXN5bmMgZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gYGF1dGgvJHtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfUkVDQVBUQ0hBX1RPS0VOfWApIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGAke2FjdGlvbk5hbWV9IGlzIHByb3RlY3RlZCBieSByZUNBUFRDSEEgRW50ZXJwcmlzZSBmb3IgdGhpcyBwcm9qZWN0LiBBdXRvbWF0aWNhbGx5IHRyaWdnZXJpbmcgdGhlIHJlQ0FQVENIQSBmbG93IGFuZCByZXN0YXJ0aW5nIHRoZSBmbG93LmBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHJlcXVlc3RXaXRoUmVjYXB0Y2hhID0gYXdhaXQgaW5qZWN0UmVjYXB0Y2hhRmllbGRzKFxuICAgICAgICAgICAgYXV0aEluc3RhbmNlLFxuICAgICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICAgIGFjdGlvbk5hbWUsXG4gICAgICAgICAgICBhY3Rpb25OYW1lID09PSBSZWNhcHRjaGFBY3Rpb25OYW1lLkdFVF9PT0JfQ09ERVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIGFjdGlvbk1ldGhvZChhdXRoSW5zdGFuY2UsIHJlcXVlc3RXaXRoUmVjYXB0Y2hhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0gZWxzZSBpZiAocmVjYXB0Y2hhQXV0aFByb3ZpZGVyID09PSBSZWNhcHRjaGFBdXRoUHJvdmlkZXIuUEhPTkVfUFJPVklERVIpIHtcbiAgICBpZiAoXG4gICAgICBhdXRoSW5zdGFuY2VcbiAgICAgICAgLl9nZXRSZWNhcHRjaGFDb25maWcoKVxuICAgICAgICA/LmlzUHJvdmlkZXJFbmFibGVkKFJlY2FwdGNoYUF1dGhQcm92aWRlci5QSE9ORV9QUk9WSURFUilcbiAgICApIHtcbiAgICAgIGNvbnN0IHJlcXVlc3RXaXRoUmVjYXB0Y2hhID0gYXdhaXQgaW5qZWN0UmVjYXB0Y2hhRmllbGRzKFxuICAgICAgICBhdXRoSW5zdGFuY2UsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGFjdGlvbk5hbWVcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBhY3Rpb25NZXRob2QoYXV0aEluc3RhbmNlLCByZXF1ZXN0V2l0aFJlY2FwdGNoYSkuY2F0Y2goXG4gICAgICAgIGFzeW5jIGVycm9yID0+IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBhdXRoSW5zdGFuY2VcbiAgICAgICAgICAgICAgLl9nZXRSZWNhcHRjaGFDb25maWcoKVxuICAgICAgICAgICAgICA/LmdldFByb3ZpZGVyRW5mb3JjZW1lbnRTdGF0ZShcbiAgICAgICAgICAgICAgICBSZWNhcHRjaGFBdXRoUHJvdmlkZXIuUEhPTkVfUFJPVklERVJcbiAgICAgICAgICAgICAgKSA9PT0gRW5mb3JjZW1lbnRTdGF0ZS5BVURJVFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgLy8gQVVESVQgbW9kZVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICBlcnJvci5jb2RlID09PSBgYXV0aC8ke0F1dGhFcnJvckNvZGUuTUlTU0lOR19SRUNBUFRDSEFfVE9LRU59YCB8fFxuICAgICAgICAgICAgICBlcnJvci5jb2RlID09PSBgYXV0aC8ke0F1dGhFcnJvckNvZGUuSU5WQUxJRF9BUFBfQ1JFREVOVElBTH1gXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgYEZhaWxlZCB0byB2ZXJpZnkgd2l0aCByZUNBUFRDSEEgRW50ZXJwcmlzZS4gQXV0b21hdGljYWxseSB0cmlnZ2VyaW5nIHRoZSByZUNBUFRDSEEgdjIgZmxvdyB0byBjb21wbGV0ZSB0aGUgJHthY3Rpb25OYW1lfSBmbG93LmBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgLy8gcmVDQVBUQ0hBIEVudGVycHJpc2UgdG9rZW4gaXMgbWlzc2luZyBvciByZUNBUFRDSEEgRW50ZXJwcmlzZSB0b2tlblxuICAgICAgICAgICAgICAvLyBjaGVjayBmYWlscy5cbiAgICAgICAgICAgICAgLy8gRmFsbGJhY2sgdG8gcmVDQVBUQ0hBIHYyIGZsb3cuXG4gICAgICAgICAgICAgIGNvbnN0IHJlcXVlc3RXaXRoUmVjYXB0Y2hhRmllbGRzID0gYXdhaXQgaW5qZWN0UmVjYXB0Y2hhRmllbGRzKFxuICAgICAgICAgICAgICAgIGF1dGhJbnN0YW5jZSxcbiAgICAgICAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgICAgICAgIGFjdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgZmFsc2UsIC8vIGlzQ2FwdGNoYVJlc3BcbiAgICAgICAgICAgICAgICB0cnVlIC8vIGlzRmFrZVRva2VuXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBjYWxsIHRoZSBQaG9uZUFwaUNhbGxlciB0byBmZXRjaCBhbmQgaW5qZWN0IHJlQ0FQVENIQSB2MiB0b2tlbi5cbiAgICAgICAgICAgICAgcmV0dXJuIGFjdGlvbk1ldGhvZChhdXRoSW5zdGFuY2UsIHJlcXVlc3RXaXRoUmVjYXB0Y2hhRmllbGRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gRU5GT1JDRSBtb2RlIG9yIEFVRElUIG1vZGUgd2l0aCBhbnkgb3RoZXIgZXJyb3IuXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRG8gcmVDQVBUQ0hBIHYyIGZsb3cuXG4gICAgICBjb25zdCByZXF1ZXN0V2l0aFJlY2FwdGNoYUZpZWxkcyA9IGF3YWl0IGluamVjdFJlY2FwdGNoYUZpZWxkcyhcbiAgICAgICAgYXV0aEluc3RhbmNlLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBhY3Rpb25OYW1lLFxuICAgICAgICBmYWxzZSwgLy8gaXNDYXB0Y2hhUmVzcFxuICAgICAgICB0cnVlIC8vIGlzRmFrZVRva2VuXG4gICAgICApO1xuXG4gICAgICAvLyBUaGlzIHdpbGwgY2FsbCB0aGUgUGhvbmVBcGlDYWxsZXIgdG8gZmV0Y2ggYW5kIGluamVjdCB2MiB0b2tlbi5cbiAgICAgIHJldHVybiBhY3Rpb25NZXRob2QoYXV0aEluc3RhbmNlLCByZXF1ZXN0V2l0aFJlY2FwdGNoYUZpZWxkcyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIHJlY2FwdGNoYUF1dGhQcm92aWRlciArICcgcHJvdmlkZXIgaXMgbm90IHN1cHBvcnRlZC4nXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX2luaXRpYWxpemVSZWNhcHRjaGFDb25maWcoYXV0aDogQXV0aCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBnZXRSZWNhcHRjaGFDb25maWcoYXV0aEludGVybmFsLCB7XG4gICAgY2xpZW50VHlwZTogUmVjYXB0Y2hhQ2xpZW50VHlwZS5XRUIsXG4gICAgdmVyc2lvbjogUmVjYXB0Y2hhVmVyc2lvbi5FTlRFUlBSSVNFXG4gIH0pO1xuXG4gIGNvbnN0IGNvbmZpZyA9IG5ldyBSZWNhcHRjaGFDb25maWcocmVzcG9uc2UpO1xuICBpZiAoYXV0aEludGVybmFsLnRlbmFudElkID09IG51bGwpIHtcbiAgICBhdXRoSW50ZXJuYWwuX2FnZW50UmVjYXB0Y2hhQ29uZmlnID0gY29uZmlnO1xuICB9IGVsc2Uge1xuICAgIGF1dGhJbnRlcm5hbC5fdGVuYW50UmVjYXB0Y2hhQ29uZmlnc1thdXRoSW50ZXJuYWwudGVuYW50SWRdID0gY29uZmlnO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5pc0FueVByb3ZpZGVyRW5hYmxlZCgpKSB7XG4gICAgY29uc3QgdmVyaWZpZXIgPSBuZXcgUmVjYXB0Y2hhRW50ZXJwcmlzZVZlcmlmaWVyKGF1dGhJbnRlcm5hbCk7XG4gICAgdm9pZCB2ZXJpZmllci52ZXJpZnkoKTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IF9nZXRQcm92aWRlciwgRmlyZWJhc2VBcHAgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IGRlZXBFcXVhbCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEF1dGgsIERlcGVuZGVuY2llcyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgUGVyc2lzdGVuY2VJbnRlcm5hbCB9IGZyb20gJy4uL3BlcnNpc3RlbmNlJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgX2dldEluc3RhbmNlIH0gZnJvbSAnLi4vdXRpbC9pbnN0YW50aWF0b3InO1xuaW1wb3J0IHsgQXV0aEltcGwgfSBmcm9tICcuL2F1dGhfaW1wbCc7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4ge0BsaW5rIEF1dGh9IGluc3RhbmNlIHdpdGggZmluZS1ncmFpbmVkIGNvbnRyb2wgb3ZlclxuICoge0BsaW5rIERlcGVuZGVuY2llc30uXG4gKlxuICogQHJlbWFya3NcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGFsbG93cyBtb3JlIGNvbnRyb2wgb3ZlciB0aGUge0BsaW5rIEF1dGh9IGluc3RhbmNlIHRoYW5cbiAqIHtAbGluayBnZXRBdXRofS4gYGdldEF1dGhgIHVzZXMgcGxhdGZvcm0tc3BlY2lmaWMgZGVmYXVsdHMgdG8gc3VwcGx5XG4gKiB0aGUge0BsaW5rIERlcGVuZGVuY2llc30uIEluIGdlbmVyYWwsIGBnZXRBdXRoYCBpcyB0aGUgZWFzaWVzdCB3YXkgdG9cbiAqIGluaXRpYWxpemUgQXV0aCBhbmQgd29ya3MgZm9yIG1vc3QgdXNlIGNhc2VzLiBVc2UgYGluaXRpYWxpemVBdXRoYCBpZiB5b3VcbiAqIG5lZWQgY29udHJvbCBvdmVyIHdoaWNoIHBlcnNpc3RlbmNlIGxheWVyIGlzIHVzZWQsIG9yIHRvIG1pbmltaXplIGJ1bmRsZVxuICogc2l6ZSBpZiB5b3UncmUgbm90IHVzaW5nIGVpdGhlciBgc2lnbkluV2l0aFBvcHVwYCBvciBgc2lnbkluV2l0aFJlZGlyZWN0YC5cbiAqXG4gKiBGb3IgZXhhbXBsZSwgaWYgeW91ciBhcHAgb25seSB1c2VzIGFub255bW91cyBhY2NvdW50cyBhbmQgeW91IG9ubHkgd2FudFxuICogYWNjb3VudHMgc2F2ZWQgZm9yIHRoZSBjdXJyZW50IHNlc3Npb24sIGluaXRpYWxpemUgYEF1dGhgIHdpdGg6XG4gKlxuICogYGBganNcbiAqIGNvbnN0IGF1dGggPSBpbml0aWFsaXplQXV0aChhcHAsIHtcbiAqICAgcGVyc2lzdGVuY2U6IGJyb3dzZXJTZXNzaW9uUGVyc2lzdGVuY2UsXG4gKiAgIHBvcHVwUmVkaXJlY3RSZXNvbHZlcjogdW5kZWZpbmVkLFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplQXV0aChhcHA6IEZpcmViYXNlQXBwLCBkZXBzPzogRGVwZW5kZW5jaWVzKTogQXV0aCB7XG4gIGNvbnN0IHByb3ZpZGVyID0gX2dldFByb3ZpZGVyKGFwcCwgJ2F1dGgnKTtcblxuICBpZiAocHJvdmlkZXIuaXNJbml0aWFsaXplZCgpKSB7XG4gICAgY29uc3QgYXV0aCA9IHByb3ZpZGVyLmdldEltbWVkaWF0ZSgpIGFzIEF1dGhJbXBsO1xuICAgIGNvbnN0IGluaXRpYWxPcHRpb25zID0gcHJvdmlkZXIuZ2V0T3B0aW9ucygpIGFzIERlcGVuZGVuY2llcztcbiAgICBpZiAoZGVlcEVxdWFsKGluaXRpYWxPcHRpb25zLCBkZXBzID8/IHt9KSkge1xuICAgICAgcmV0dXJuIGF1dGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuQUxSRUFEWV9JTklUSUFMSVpFRCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgYXV0aCA9IHByb3ZpZGVyLmluaXRpYWxpemUoeyBvcHRpb25zOiBkZXBzIH0pIGFzIEF1dGhJbXBsO1xuXG4gIHJldHVybiBhdXRoO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2luaXRpYWxpemVBdXRoSW5zdGFuY2UoXG4gIGF1dGg6IEF1dGhJbXBsLFxuICBkZXBzPzogRGVwZW5kZW5jaWVzXG4pOiB2b2lkIHtcbiAgY29uc3QgcGVyc2lzdGVuY2UgPSBkZXBzPy5wZXJzaXN0ZW5jZSB8fCBbXTtcbiAgY29uc3QgaGllcmFyY2h5ID0gKFxuICAgIEFycmF5LmlzQXJyYXkocGVyc2lzdGVuY2UpID8gcGVyc2lzdGVuY2UgOiBbcGVyc2lzdGVuY2VdXG4gICkubWFwPFBlcnNpc3RlbmNlSW50ZXJuYWw+KF9nZXRJbnN0YW5jZSk7XG4gIGlmIChkZXBzPy5lcnJvck1hcCkge1xuICAgIGF1dGguX3VwZGF0ZUVycm9yTWFwKGRlcHMuZXJyb3JNYXApO1xuICB9XG5cbiAgLy8gVGhpcyBwcm9taXNlIGlzIGludGVuZGVkIHRvIGZsb2F0OyBhdXRoIGluaXRpYWxpemF0aW9uIGhhcHBlbnMgaW4gdGhlXG4gIC8vIGJhY2tncm91bmQsIG1lYW53aGlsZSB0aGUgYXV0aCBvYmplY3QgbWF5IGJlIHVzZWQgYnkgdGhlIGFwcC5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICBhdXRoLl9pbml0aWFsaXplV2l0aFBlcnNpc3RlbmNlKGhpZXJhcmNoeSwgZGVwcz8ucG9wdXBSZWRpcmVjdFJlc29sdmVyKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfY2FzdEF1dGggfSBmcm9tICcuL2F1dGhfaW1wbCc7XG5pbXBvcnQge1xuICBkZWVwRXF1YWwsXG4gIGlzQ2xvdWRXb3Jrc3RhdGlvbixcbiAgcGluZ1NlcnZlcixcbiAgdXBkYXRlRW11bGF0b3JCYW5uZXJcbn0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vKipcbiAqIENoYW5nZXMgdGhlIHtAbGluayBBdXRofSBpbnN0YW5jZSB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBGaXJlYmFzZSBBdXRoIEVtdWxhdG9yLCBpbnN0ZWFkIG9mIHByb2R1Y3Rpb25cbiAqIEZpcmViYXNlIEF1dGggc2VydmljZXMuXG4gKlxuICogQHJlbWFya3NcbiAqIFRoaXMgbXVzdCBiZSBjYWxsZWQgc3luY2hyb25vdXNseSBpbW1lZGlhdGVseSBmb2xsb3dpbmcgdGhlIGZpcnN0IGNhbGwgdG9cbiAqIHtAbGluayBpbml0aWFsaXplQXV0aH0uICBEbyBub3QgdXNlIHdpdGggcHJvZHVjdGlvbiBjcmVkZW50aWFscyBhcyBlbXVsYXRvclxuICogdHJhZmZpYyBpcyBub3QgZW5jcnlwdGVkLlxuICpcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogY29ubmVjdEF1dGhFbXVsYXRvcihhdXRoLCAnaHR0cDovLzEyNy4wLjAuMTo5MDk5JywgeyBkaXNhYmxlV2FybmluZ3M6IHRydWUgfSk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCBhdCB3aGljaCB0aGUgZW11bGF0b3IgaXMgcnVubmluZyAoZWcsICdodHRwOi8vbG9jYWxob3N0OjkwOTknKS5cbiAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9uYWwuIGBvcHRpb25zLmRpc2FibGVXYXJuaW5nc2AgZGVmYXVsdHMgdG8gYGZhbHNlYC4gU2V0IGl0IHRvXG4gKiBgdHJ1ZWAgdG8gZGlzYWJsZSB0aGUgd2FybmluZyBiYW5uZXIgYXR0YWNoZWQgdG8gdGhlIERPTS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25uZWN0QXV0aEVtdWxhdG9yKFxuICBhdXRoOiBBdXRoLFxuICB1cmw6IHN0cmluZyxcbiAgb3B0aW9ucz86IHsgZGlzYWJsZVdhcm5pbmdzOiBib29sZWFuIH1cbik6IHZvaWQge1xuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG4gIF9hc3NlcnQoXG4gICAgL15odHRwcz86XFwvXFwvLy50ZXN0KHVybCksXG4gICAgYXV0aEludGVybmFsLFxuICAgIEF1dGhFcnJvckNvZGUuSU5WQUxJRF9FTVVMQVRPUl9TQ0hFTUVcbiAgKTtcblxuICBjb25zdCBkaXNhYmxlV2FybmluZ3MgPSAhIW9wdGlvbnM/LmRpc2FibGVXYXJuaW5ncztcblxuICBjb25zdCBwcm90b2NvbCA9IGV4dHJhY3RQcm90b2NvbCh1cmwpO1xuICBjb25zdCB7IGhvc3QsIHBvcnQgfSA9IGV4dHJhY3RIb3N0QW5kUG9ydCh1cmwpO1xuICBjb25zdCBwb3J0U3RyID0gcG9ydCA9PT0gbnVsbCA/ICcnIDogYDoke3BvcnR9YDtcblxuICAvLyBBbHdheXMgcmVwbGFjZSBwYXRoIHdpdGggXCIvXCIgKGV2ZW4gaWYgaW5wdXQgdXJsIGhhZCBubyBwYXRoIGF0IGFsbCwgb3IgaGFkIGEgZGlmZmVyZW50IG9uZSkuXG4gIGNvbnN0IGVtdWxhdG9yID0geyB1cmw6IGAke3Byb3RvY29sfS8vJHtob3N0fSR7cG9ydFN0cn0vYCB9O1xuICBjb25zdCBlbXVsYXRvckNvbmZpZyA9IE9iamVjdC5mcmVlemUoe1xuICAgIGhvc3QsXG4gICAgcG9ydCxcbiAgICBwcm90b2NvbDogcHJvdG9jb2wucmVwbGFjZSgnOicsICcnKSxcbiAgICBvcHRpb25zOiBPYmplY3QuZnJlZXplKHsgZGlzYWJsZVdhcm5pbmdzIH0pXG4gIH0pO1xuXG4gIC8vIFRoZXJlIGFyZSBhIGZldyBzY2VuYXJpb3MgdG8gZ3VhcmQgYWdhaW5zdCBpZiB0aGUgQXV0aCBpbnN0YW5jZSBoYXMgYWxyZWFkeSBzdGFydGVkOlxuICBpZiAoIWF1dGhJbnRlcm5hbC5fY2FuSW5pdEVtdWxhdG9yKSB7XG4gICAgLy8gQXBwbGljYXRpb25zIG1heSBub3QgaW5pdGlhbGl6ZSB0aGUgZW11bGF0b3IgZm9yIHRoZSBmaXJzdCB0aW1lIGlmIEF1dGggaGFzIGFscmVhZHkgc3RhcnRlZFxuICAgIC8vIHRvIG1ha2UgbmV0d29yayByZXF1ZXN0cy5cbiAgICBfYXNzZXJ0KFxuICAgICAgYXV0aEludGVybmFsLmNvbmZpZy5lbXVsYXRvciAmJiBhdXRoSW50ZXJuYWwuZW11bGF0b3JDb25maWcsXG4gICAgICBhdXRoSW50ZXJuYWwsXG4gICAgICBBdXRoRXJyb3JDb2RlLkVNVUxBVE9SX0NPTkZJR19GQUlMRURcbiAgICApO1xuXG4gICAgLy8gQXBwbGljYXRpb25zIG1heSBub3QgYWx0ZXIgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIGVtdWxhdG9yIChha2EgcGFzcyBhIGRpZmZlcmVudCBjb25maWcpXG4gICAgLy8gb25jZSBBdXRoIGhhcyBzdGFydGVkIHRvIG1ha2UgbmV0d29yayByZXF1ZXN0cy5cbiAgICBfYXNzZXJ0KFxuICAgICAgZGVlcEVxdWFsKGVtdWxhdG9yLCBhdXRoSW50ZXJuYWwuY29uZmlnLmVtdWxhdG9yKSAmJlxuICAgICAgICBkZWVwRXF1YWwoZW11bGF0b3JDb25maWcsIGF1dGhJbnRlcm5hbC5lbXVsYXRvckNvbmZpZyksXG4gICAgICBhdXRoSW50ZXJuYWwsXG4gICAgICBBdXRoRXJyb3JDb2RlLkVNVUxBVE9SX0NPTkZJR19GQUlMRURcbiAgICApO1xuXG4gICAgLy8gSXQncyB2YWxpZCwgaG93ZXZlciwgdG8gaW52b2tlIGNvbm5lY3RBdXRoRW11bGF0b3IoKSBhZnRlciBBdXRoIGhhcyBzdGFydGVkIG1ha2luZ1xuICAgIC8vIGNvbm5lY3Rpb25zLCBzbyBsb25nIGFzIHRoZSBjb25maWcgbWF0Y2hlcyB0aGUgZXhpc3RpbmcgY29uZmlnLiBUaGlzIHJlc3VsdHMgaW4gYSBuby1vcC5cbiAgICByZXR1cm47XG4gIH1cblxuICBhdXRoSW50ZXJuYWwuY29uZmlnLmVtdWxhdG9yID0gZW11bGF0b3I7XG4gIGF1dGhJbnRlcm5hbC5lbXVsYXRvckNvbmZpZyA9IGVtdWxhdG9yQ29uZmlnO1xuICBhdXRoSW50ZXJuYWwuc2V0dGluZ3MuYXBwVmVyaWZpY2F0aW9uRGlzYWJsZWRGb3JUZXN0aW5nID0gdHJ1ZTtcblxuICAvLyBXb3JrYXJvdW5kIHRvIGdldCBjb29raWVzIGluIEZpcmViYXNlIFN0dWRpb1xuICBpZiAoaXNDbG91ZFdvcmtzdGF0aW9uKGhvc3QpKSB7XG4gICAgdm9pZCBwaW5nU2VydmVyKGAke3Byb3RvY29sfS8vJHtob3N0fSR7cG9ydFN0cn1gKTtcbiAgICB1cGRhdGVFbXVsYXRvckJhbm5lcignQXV0aCcsIHRydWUpO1xuICB9IGVsc2UgaWYgKCFkaXNhYmxlV2FybmluZ3MpIHtcbiAgICBlbWl0RW11bGF0b3JXYXJuaW5nKCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZXh0cmFjdFByb3RvY29sKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcHJvdG9jb2xFbmQgPSB1cmwuaW5kZXhPZignOicpO1xuICByZXR1cm4gcHJvdG9jb2xFbmQgPCAwID8gJycgOiB1cmwuc3Vic3RyKDAsIHByb3RvY29sRW5kICsgMSk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RIb3N0QW5kUG9ydCh1cmw6IHN0cmluZyk6IHtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBudW1iZXIgfCBudWxsO1xufSB7XG4gIGNvbnN0IHByb3RvY29sID0gZXh0cmFjdFByb3RvY29sKHVybCk7XG4gIGNvbnN0IGF1dGhvcml0eSA9IC8oXFwvXFwvKT8oW14/Iy9dKykvLmV4ZWModXJsLnN1YnN0cihwcm90b2NvbC5sZW5ndGgpKTsgLy8gQmV0d2VlbiAvLyBhbmQgLywgPyBvciAjLlxuICBpZiAoIWF1dGhvcml0eSkge1xuICAgIHJldHVybiB7IGhvc3Q6ICcnLCBwb3J0OiBudWxsIH07XG4gIH1cbiAgY29uc3QgaG9zdEFuZFBvcnQgPSBhdXRob3JpdHlbMl0uc3BsaXQoJ0AnKS5wb3AoKSB8fCAnJzsgLy8gU3RyaXAgb3V0IFwidXNlcm5hbWU6cGFzc3dvcmRAXCIuXG4gIGNvbnN0IGJyYWNrZXRlZElQdjYgPSAvXihcXFtbXlxcXV0rXFxdKSg6fCQpLy5leGVjKGhvc3RBbmRQb3J0KTtcbiAgaWYgKGJyYWNrZXRlZElQdjYpIHtcbiAgICBjb25zdCBob3N0ID0gYnJhY2tldGVkSVB2NlsxXTtcbiAgICByZXR1cm4geyBob3N0LCBwb3J0OiBwYXJzZVBvcnQoaG9zdEFuZFBvcnQuc3Vic3RyKGhvc3QubGVuZ3RoICsgMSkpIH07XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgW2hvc3QsIHBvcnRdID0gaG9zdEFuZFBvcnQuc3BsaXQoJzonKTtcbiAgICByZXR1cm4geyBob3N0LCBwb3J0OiBwYXJzZVBvcnQocG9ydCkgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVBvcnQocG9ydFN0cjogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gIGlmICghcG9ydFN0cikge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHBvcnQgPSBOdW1iZXIocG9ydFN0cik7XG4gIGlmIChpc05hTihwb3J0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiBwb3J0O1xufVxuXG5mdW5jdGlvbiBlbWl0RW11bGF0b3JXYXJuaW5nKCk6IHZvaWQge1xuICBmdW5jdGlvbiBhdHRhY2hCYW5uZXIoKTogdm9pZCB7XG4gICAgY29uc3QgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwJyk7XG4gICAgY29uc3Qgc3R5ID0gZWwuc3R5bGU7XG4gICAgZWwuaW5uZXJUZXh0ID1cbiAgICAgICdSdW5uaW5nIGluIGVtdWxhdG9yIG1vZGUuIERvIG5vdCB1c2Ugd2l0aCBwcm9kdWN0aW9uIGNyZWRlbnRpYWxzLic7XG4gICAgc3R5LnBvc2l0aW9uID0gJ2ZpeGVkJztcbiAgICBzdHkud2lkdGggPSAnMTAwJSc7XG4gICAgc3R5LmJhY2tncm91bmRDb2xvciA9ICcjZmZmZmZmJztcbiAgICBzdHkuYm9yZGVyID0gJy4xZW0gc29saWQgIzAwMDAwMCc7XG4gICAgc3R5LmNvbG9yID0gJyNiNTAwMDAnO1xuICAgIHN0eS5ib3R0b20gPSAnMHB4JztcbiAgICBzdHkubGVmdCA9ICcwcHgnO1xuICAgIHN0eS5tYXJnaW4gPSAnMHB4JztcbiAgICBzdHkuekluZGV4ID0gJzEwMDAwJztcbiAgICBzdHkudGV4dEFsaWduID0gJ2NlbnRlcic7XG4gICAgZWwuY2xhc3NMaXN0LmFkZCgnZmlyZWJhc2UtZW11bGF0b3Itd2FybmluZycpO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZWwpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY29uc29sZS5pbmZvID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29uc29sZS5pbmZvKFxuICAgICAgJ1dBUk5JTkc6IFlvdSBhcmUgdXNpbmcgdGhlIEF1dGggRW11bGF0b3IsJyArXG4gICAgICAgICcgd2hpY2ggaXMgaW50ZW5kZWQgZm9yIGxvY2FsIHRlc3Rpbmcgb25seS4gIERvIG5vdCB1c2Ugd2l0aCcgK1xuICAgICAgICAnIHByb2R1Y3Rpb24gY3JlZGVudGlhbHMuJ1xuICAgICk7XG4gIH1cbiAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGF0dGFjaEJhbm5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF0dGFjaEJhbm5lcigpO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgZGVidWdGYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIEludGVyZmFjZSB0aGF0IHJlcHJlc2VudHMgdGhlIGNyZWRlbnRpYWxzIHJldHVybmVkIGJ5IGFuIHtAbGluayBBdXRoUHJvdmlkZXJ9LlxuICpcbiAqIEByZW1hcmtzXG4gKiBJbXBsZW1lbnRhdGlvbnMgc3BlY2lmeSB0aGUgZGV0YWlscyBhYm91dCBlYWNoIGF1dGggcHJvdmlkZXIncyBjcmVkZW50aWFsIHJlcXVpcmVtZW50cy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoQ3JlZGVudGlhbCB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIC8qKlxuICAgICAqIFRoZSBhdXRoZW50aWNhdGlvbiBwcm92aWRlciBJRCBmb3IgdGhlIGNyZWRlbnRpYWwuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIEZvciBleGFtcGxlLCAnZmFjZWJvb2suY29tJywgb3IgJ2dvb2dsZS5jb20nLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IHByb3ZpZGVySWQ6IHN0cmluZyxcbiAgICAvKipcbiAgICAgKiBUaGUgYXV0aGVudGljYXRpb24gc2lnbiBpbiBtZXRob2QgZm9yIHRoZSBjcmVkZW50aWFsLlxuICAgICAqXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBGb3IgZXhhbXBsZSwge0BsaW5rIFNpZ25Jbk1ldGhvZH0uRU1BSUxfUEFTU1dPUkQsIG9yXG4gICAgICoge0BsaW5rIFNpZ25Jbk1ldGhvZH0uRU1BSUxfTElOSy4gVGhpcyBjb3JyZXNwb25kcyB0byB0aGUgc2lnbi1pbiBtZXRob2RcbiAgICAgKiBpZGVudGlmaWVyIGFzIHJldHVybmVkIGluIHtAbGluayBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbH0uXG4gICAgICovXG4gICAgcmVhZG9ubHkgc2lnbkluTWV0aG9kOiBzdHJpbmdcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgSlNPTi1zZXJpYWxpemFibGUgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvYmplY3QuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgSlNPTi1zZXJpYWxpemFibGUgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvYmplY3QuXG4gICAqL1xuICB0b0pTT04oKTogb2JqZWN0IHtcbiAgICByZXR1cm4gZGVidWdGYWlsKCdub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX2dldElkVG9rZW5SZXNwb25zZShfYXV0aDogQXV0aEludGVybmFsKTogUHJvbWlzZTxQaG9uZU9yT2F1dGhUb2tlblJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIGRlYnVnRmFpbCgnbm90IGltcGxlbWVudGVkJyk7XG4gIH1cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfbGlua1RvSWRUb2tlbihcbiAgICBfYXV0aDogQXV0aEludGVybmFsLFxuICAgIF9pZFRva2VuOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICByZXR1cm4gZGVidWdGYWlsKCdub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuICAvKiogQGludGVybmFsICovXG4gIF9nZXRSZWF1dGhlbnRpY2F0aW9uUmVzb2x2ZXIoX2F1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIGRlYnVnRmFpbCgnbm90IGltcGxlbWVudGVkJyk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBY3Rpb25Db2RlT3BlcmF0aW9uLCBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHtcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeSxcbiAgX3BlcmZvcm1BcGlSZXF1ZXN0XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IE1mYUVucm9sbG1lbnQgfSBmcm9tICcuL21mYSc7XG5pbXBvcnQgeyBTaWduVXBSZXF1ZXN0LCBTaWduVXBSZXNwb25zZSB9IGZyb20gJy4uL2F1dGhlbnRpY2F0aW9uL3NpZ25fdXAnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc2V0UGFzc3dvcmRSZXF1ZXN0IHtcbiAgb29iQ29kZTogc3RyaW5nO1xuICBuZXdQYXNzd29yZD86IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzZXRQYXNzd29yZFJlc3BvbnNlIHtcbiAgZW1haWw6IHN0cmluZztcbiAgbmV3RW1haWw/OiBzdHJpbmc7XG4gIHJlcXVlc3RUeXBlPzogQWN0aW9uQ29kZU9wZXJhdGlvbjtcbiAgbWZhSW5mbz86IE1mYUVucm9sbG1lbnQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNldFBhc3N3b3JkKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBSZXNldFBhc3N3b3JkUmVxdWVzdFxuKTogUHJvbWlzZTxSZXNldFBhc3N3b3JkUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxSZXNldFBhc3N3b3JkUmVxdWVzdCwgUmVzZXRQYXNzd29yZFJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5SRVNFVF9QQVNTV09SRCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHJldHVyblNlY3VyZVRva2VuPzogYm9vbGVhbjtcbiAgZW1haWw/OiBzdHJpbmc7XG4gIHBhc3N3b3JkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZUVtYWlsUGFzc3dvcmRSZXNwb25zZSBleHRlbmRzIElkVG9rZW5SZXNwb25zZSB7fVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlRW1haWxQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3Rcbik6IFByb21pc2U8VXBkYXRlRW1haWxQYXNzd29yZFJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3QsXG4gICAgVXBkYXRlRW1haWxQYXNzd29yZFJlc3BvbnNlXG4gID4oYXV0aCwgSHR0cE1ldGhvZC5QT1NULCBFbmRwb2ludC5TRVRfQUNDT1VOVF9JTkZPLCByZXF1ZXN0KTtcbn1cblxuLy8gVXNlZCBmb3IgbGlua2luZyBhbiBlbWFpbC9wYXNzd29yZCBhY2NvdW50IHRvIGFuIGV4aXN0aW5nIGlkVG9rZW4uIFVzZXMgdGhlIHNhbWUgcmVxdWVzdC9yZXNwb25zZVxuLy8gZm9ybWF0IGFzIHVwZGF0ZUVtYWlsUGFzc3dvcmQuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlua0VtYWlsUGFzc3dvcmQoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25VcFJlcXVlc3Rcbik6IFByb21pc2U8U2lnblVwUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxTaWduVXBSZXF1ZXN0LCBTaWduVXBSZXNwb25zZT4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9VUCxcbiAgICByZXF1ZXN0XG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbHlBY3Rpb25Db2RlUmVxdWVzdCB7XG4gIG9vYkNvZGU6IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbHlBY3Rpb25Db2RlUmVzcG9uc2Uge31cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFwcGx5QWN0aW9uQ29kZShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogQXBwbHlBY3Rpb25Db2RlUmVxdWVzdFxuKTogUHJvbWlzZTxBcHBseUFjdGlvbkNvZGVSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PEFwcGx5QWN0aW9uQ29kZVJlcXVlc3QsIEFwcGx5QWN0aW9uQ29kZVJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TRVRfQUNDT1VOVF9JTkZPLFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEFjdGlvbkNvZGVPcGVyYXRpb24sIEF1dGggfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQge1xuICBFbmRwb2ludCxcbiAgSHR0cE1ldGhvZCxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhVmVyc2lvbixcbiAgX2FkZFRpZElmTmVjZXNzYXJ5LFxuICBfcGVyZm9ybUFwaVJlcXVlc3QsXG4gIF9wZXJmb3JtU2lnbkluUmVxdWVzdFxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJZFRva2VuLCBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aFBhc3N3b3JkUmVxdWVzdCB7XG4gIHJldHVyblNlY3VyZVRva2VuPzogYm9vbGVhbjtcbiAgZW1haWw6IHN0cmluZztcbiAgcGFzc3dvcmQ6IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG4gIGNhcHRjaGFSZXNwb25zZT86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhQYXNzd29yZFJlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHtcbiAgZW1haWw6IHN0cmluZztcbiAgZGlzcGxheU5hbWU6IHN0cmluZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbldpdGhQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2lnbkluV2l0aFBhc3N3b3JkUmVxdWVzdFxuKTogUHJvbWlzZTxTaWduSW5XaXRoUGFzc3dvcmRSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFxuICAgIFNpZ25JbldpdGhQYXNzd29yZFJlcXVlc3QsXG4gICAgU2lnbkluV2l0aFBhc3N3b3JkUmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfUEFTU1dPUkQsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0T29iQ29kZVJlcXVlc3Qge1xuICBlbWFpbD86IHN0cmluZzsgLy8gRXZlcnl0aGluZyBleGNlcHQgVkVSSUZZX0FORF9DSEFOR0VfRU1BSUxcbiAgY29udGludWVVcmw/OiBzdHJpbmc7XG4gIGlPU0J1bmRsZUlkPzogc3RyaW5nO1xuICBpb3NBcHBTdG9yZUlkPzogc3RyaW5nO1xuICBhbmRyb2lkUGFja2FnZU5hbWU/OiBzdHJpbmc7XG4gIGFuZHJvaWRJbnN0YWxsQXBwPzogYm9vbGVhbjtcbiAgYW5kcm9pZE1pbmltdW1WZXJzaW9uQ29kZT86IHN0cmluZztcbiAgY2FuSGFuZGxlQ29kZUluQXBwPzogYm9vbGVhbjtcbiAgZHluYW1pY0xpbmtEb21haW4/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICB0YXJnZXRQcm9qZWN0aWQ/OiBzdHJpbmc7XG4gIGxpbmtEb21haW4/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmVyaWZ5RW1haWxSZXF1ZXN0IGV4dGVuZHMgR2V0T29iQ29kZVJlcXVlc3Qge1xuICByZXF1ZXN0VHlwZTogQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfRU1BSUw7XG4gIGlkVG9rZW46IElkVG9rZW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRSZXNldFJlcXVlc3QgZXh0ZW5kcyBHZXRPb2JDb2RlUmVxdWVzdCB7XG4gIHJlcXVlc3RUeXBlOiBBY3Rpb25Db2RlT3BlcmF0aW9uLlBBU1NXT1JEX1JFU0VUO1xuICBlbWFpbDogc3RyaW5nO1xuICBjYXB0Y2hhUmVzcD86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVtYWlsU2lnbkluUmVxdWVzdCBleHRlbmRzIEdldE9vYkNvZGVSZXF1ZXN0IHtcbiAgcmVxdWVzdFR5cGU6IEFjdGlvbkNvZGVPcGVyYXRpb24uRU1BSUxfU0lHTklOO1xuICBlbWFpbDogc3RyaW5nO1xuICBjYXB0Y2hhUmVzcD86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZlcmlmeUFuZENoYW5nZUVtYWlsUmVxdWVzdCBleHRlbmRzIEdldE9vYkNvZGVSZXF1ZXN0IHtcbiAgcmVxdWVzdFR5cGU6IEFjdGlvbkNvZGVPcGVyYXRpb24uVkVSSUZZX0FORF9DSEFOR0VfRU1BSUw7XG4gIGlkVG9rZW46IElkVG9rZW47XG4gIG5ld0VtYWlsOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBHZXRPb2JDb2RlUmVzcG9uc2Uge1xuICBlbWFpbDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZlcmlmeUVtYWlsUmVzcG9uc2UgZXh0ZW5kcyBHZXRPb2JDb2RlUmVzcG9uc2Uge31cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRSZXNldFJlc3BvbnNlIGV4dGVuZHMgR2V0T29iQ29kZVJlc3BvbnNlIHt9XG5leHBvcnQgaW50ZXJmYWNlIEVtYWlsU2lnbkluUmVzcG9uc2UgZXh0ZW5kcyBHZXRPb2JDb2RlUmVzcG9uc2Uge31cbmV4cG9ydCBpbnRlcmZhY2UgVmVyaWZ5QW5kQ2hhbmdlRW1haWxSZXNwb25zZSBleHRlbmRzIEdldE9vYkNvZGVSZXF1ZXN0IHt9XG5cbmFzeW5jIGZ1bmN0aW9uIHNlbmRPb2JDb2RlKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBHZXRPb2JDb2RlUmVxdWVzdFxuKTogUHJvbWlzZTxHZXRPb2JDb2RlUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxHZXRPb2JDb2RlUmVxdWVzdCwgR2V0T29iQ29kZVJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TRU5EX09PQl9DT0RFLFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZEVtYWlsVmVyaWZpY2F0aW9uKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBWZXJpZnlFbWFpbFJlcXVlc3Rcbik6IFByb21pc2U8VmVyaWZ5RW1haWxSZXNwb25zZT4ge1xuICByZXR1cm4gc2VuZE9vYkNvZGUoYXV0aCwgcmVxdWVzdCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kUGFzc3dvcmRSZXNldEVtYWlsKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBQYXNzd29yZFJlc2V0UmVxdWVzdFxuKTogUHJvbWlzZTxQYXNzd29yZFJlc2V0UmVzcG9uc2U+IHtcbiAgcmV0dXJuIHNlbmRPb2JDb2RlKGF1dGgsIHJlcXVlc3QpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZFNpZ25JbkxpbmtUb0VtYWlsKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBFbWFpbFNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8RW1haWxTaWduSW5SZXNwb25zZT4ge1xuICByZXR1cm4gc2VuZE9vYkNvZGUoYXV0aCwgcmVxdWVzdCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlBbmRDaGFuZ2VFbWFpbChcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogVmVyaWZ5QW5kQ2hhbmdlRW1haWxSZXF1ZXN0XG4pOiBQcm9taXNlPFZlcmlmeUFuZENoYW5nZUVtYWlsUmVzcG9uc2U+IHtcbiAgcmV0dXJuIHNlbmRPb2JDb2RlKGF1dGgsIHJlcXVlc3QpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIF9wZXJmb3JtU2lnbkluUmVxdWVzdCxcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeVxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTaWduSW5XaXRoRW1haWxMaW5rUmVxdWVzdCB7XG4gIGVtYWlsOiBzdHJpbmc7XG4gIG9vYkNvZGU6IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aEVtYWlsTGlua1Jlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHtcbiAgZW1haWw6IHN0cmluZztcbiAgaXNOZXdVc2VyOiBib29sZWFuO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aEVtYWlsTGluayhcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2lnbkluV2l0aEVtYWlsTGlua1JlcXVlc3Rcbik6IFByb21pc2U8U2lnbkluV2l0aEVtYWlsTGlua1Jlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybVNpZ25JblJlcXVlc3Q8XG4gICAgU2lnbkluV2l0aEVtYWlsTGlua1JlcXVlc3QsXG4gICAgU2lnbkluV2l0aEVtYWlsTGlua1Jlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9JTl9XSVRIX0VNQUlMX0xJTkssXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aEVtYWlsTGlua0ZvckxpbmtpbmdSZXF1ZXN0XG4gIGV4dGVuZHMgU2lnbkluV2l0aEVtYWlsTGlua1JlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduSW5XaXRoRW1haWxMaW5rRm9yTGlua2luZyhcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2lnbkluV2l0aEVtYWlsTGlua0ZvckxpbmtpbmdSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhFbWFpbExpbmtSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFxuICAgIFNpZ25JbldpdGhFbWFpbExpbmtGb3JMaW5raW5nUmVxdWVzdCxcbiAgICBTaWduSW5XaXRoRW1haWxMaW5rUmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfRU1BSUxfTElOSyxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBQcm92aWRlcklkLCBTaWduSW5NZXRob2QgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5cbmltcG9ydCB7IGxpbmtFbWFpbFBhc3N3b3JkIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9lbWFpbF9hbmRfcGFzc3dvcmQnO1xuaW1wb3J0IHtcbiAgc2lnbkluV2l0aFBhc3N3b3JkLFxuICBTaWduSW5XaXRoUGFzc3dvcmRSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9lbWFpbF9hbmRfcGFzc3dvcmQnO1xuaW1wb3J0IHtcbiAgc2lnbkluV2l0aEVtYWlsTGluayxcbiAgc2lnbkluV2l0aEVtYWlsTGlua0Zvckxpbmtpbmdcbn0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2xpbmsnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2F1dGhfY3JlZGVudGlhbCc7XG5pbXBvcnQgeyBoYW5kbGVSZWNhcHRjaGFGbG93IH0gZnJvbSAnLi4vLi4vcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXInO1xuaW1wb3J0IHtcbiAgUmVjYXB0Y2hhQWN0aW9uTmFtZSxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyXG59IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQgeyBTaWduVXBSZXF1ZXN0IH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL3NpZ25fdXAnO1xuLyoqXG4gKiBJbnRlcmZhY2UgdGhhdCByZXByZXNlbnRzIHRoZSBjcmVkZW50aWFscyByZXR1cm5lZCBieSB7QGxpbmsgRW1haWxBdXRoUHJvdmlkZXJ9IGZvclxuICoge0BsaW5rIFByb3ZpZGVySWR9LlBBU1NXT1JEXG4gKlxuICogQHJlbWFya3NcbiAqIENvdmVycyBib3RoIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX1BBU1NXT1JEIGFuZFxuICoge0BsaW5rIFNpZ25Jbk1ldGhvZH0uRU1BSUxfTElOSy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBFbWFpbEF1dGhDcmVkZW50aWFsIGV4dGVuZHMgQXV0aENyZWRlbnRpYWwge1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIHJlYWRvbmx5IF9lbWFpbDogc3RyaW5nLFxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICByZWFkb25seSBfcGFzc3dvcmQ6IHN0cmluZyxcbiAgICBzaWduSW5NZXRob2Q6IFNpZ25Jbk1ldGhvZCxcbiAgICAvKiogQGludGVybmFsICovXG4gICAgcmVhZG9ubHkgX3RlbmFudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICApIHtcbiAgICBzdXBlcihQcm92aWRlcklkLlBBU1NXT1JELCBzaWduSW5NZXRob2QpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX2Zyb21FbWFpbEFuZFBhc3N3b3JkKFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBFbWFpbEF1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gbmV3IEVtYWlsQXV0aENyZWRlbnRpYWwoXG4gICAgICBlbWFpbCxcbiAgICAgIHBhc3N3b3JkLFxuICAgICAgU2lnbkluTWV0aG9kLkVNQUlMX1BBU1NXT1JEXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tRW1haWxBbmRDb2RlKFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgb29iQ29kZTogc3RyaW5nLFxuICAgIHRlbmFudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICApOiBFbWFpbEF1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gbmV3IEVtYWlsQXV0aENyZWRlbnRpYWwoXG4gICAgICBlbWFpbCxcbiAgICAgIG9vYkNvZGUsXG4gICAgICBTaWduSW5NZXRob2QuRU1BSUxfTElOSyxcbiAgICAgIHRlbmFudElkXG4gICAgKTtcbiAgfVxuXG4gIC8qKiB7QGluaGVyaXRkb2MgQXV0aENyZWRlbnRpYWwudG9KU09OfSAqL1xuICB0b0pTT04oKTogb2JqZWN0IHtcbiAgICByZXR1cm4ge1xuICAgICAgZW1haWw6IHRoaXMuX2VtYWlsLFxuICAgICAgcGFzc3dvcmQ6IHRoaXMuX3Bhc3N3b3JkLFxuICAgICAgc2lnbkluTWV0aG9kOiB0aGlzLnNpZ25Jbk1ldGhvZCxcbiAgICAgIHRlbmFudElkOiB0aGlzLl90ZW5hbnRJZFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU3RhdGljIG1ldGhvZCB0byBkZXNlcmlhbGl6ZSBhIEpTT04gcmVwcmVzZW50YXRpb24gb2YgYW4gb2JqZWN0IGludG8gYW4ge0BsaW5rICBBdXRoQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSBqc29uIC0gRWl0aGVyIGBvYmplY3RgIG9yIHRoZSBzdHJpbmdpZmllZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JqZWN0LiBXaGVuIHN0cmluZyBpc1xuICAgKiBwcm92aWRlZCwgYEpTT04ucGFyc2VgIHdvdWxkIGJlIGNhbGxlZCBmaXJzdC5cbiAgICpcbiAgICogQHJldHVybnMgSWYgdGhlIEpTT04gaW5wdXQgZG9lcyBub3QgcmVwcmVzZW50IGFuIHtAbGluayBBdXRoQ3JlZGVudGlhbH0sIG51bGwgaXMgcmV0dXJuZWQuXG4gICAqL1xuICBzdGF0aWMgZnJvbUpTT04oanNvbjogb2JqZWN0IHwgc3RyaW5nKTogRW1haWxBdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGNvbnN0IG9iaiA9IHR5cGVvZiBqc29uID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UoanNvbikgOiBqc29uO1xuICAgIGlmIChvYmo/LmVtYWlsICYmIG9iaj8ucGFzc3dvcmQpIHtcbiAgICAgIGlmIChvYmouc2lnbkluTWV0aG9kID09PSBTaWduSW5NZXRob2QuRU1BSUxfUEFTU1dPUkQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zyb21FbWFpbEFuZFBhc3N3b3JkKG9iai5lbWFpbCwgb2JqLnBhc3N3b3JkKTtcbiAgICAgIH0gZWxzZSBpZiAob2JqLnNpZ25Jbk1ldGhvZCA9PT0gU2lnbkluTWV0aG9kLkVNQUlMX0xJTkspIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zyb21FbWFpbEFuZENvZGUob2JqLmVtYWlsLCBvYmoucGFzc3dvcmQsIG9iai50ZW5hbnRJZCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBhc3luYyBfZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgc3dpdGNoICh0aGlzLnNpZ25Jbk1ldGhvZCkge1xuICAgICAgY2FzZSBTaWduSW5NZXRob2QuRU1BSUxfUEFTU1dPUkQ6XG4gICAgICAgIGNvbnN0IHJlcXVlc3Q6IFNpZ25JbldpdGhQYXNzd29yZFJlcXVlc3QgPSB7XG4gICAgICAgICAgcmV0dXJuU2VjdXJlVG9rZW46IHRydWUsXG4gICAgICAgICAgZW1haWw6IHRoaXMuX2VtYWlsLFxuICAgICAgICAgIHBhc3N3b3JkOiB0aGlzLl9wYXNzd29yZCxcbiAgICAgICAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgUmVjYXB0Y2hhQWN0aW9uTmFtZS5TSUdOX0lOX1dJVEhfUEFTU1dPUkQsXG4gICAgICAgICAgc2lnbkluV2l0aFBhc3N3b3JkLFxuICAgICAgICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICAgICAgICApO1xuICAgICAgY2FzZSBTaWduSW5NZXRob2QuRU1BSUxfTElOSzpcbiAgICAgICAgcmV0dXJuIHNpZ25JbldpdGhFbWFpbExpbmsoYXV0aCwge1xuICAgICAgICAgIGVtYWlsOiB0aGlzLl9lbWFpbCxcbiAgICAgICAgICBvb2JDb2RlOiB0aGlzLl9wYXNzd29yZFxuICAgICAgICB9KTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgYXN5bmMgX2xpbmtUb0lkVG9rZW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPElkVG9rZW5SZXNwb25zZT4ge1xuICAgIHN3aXRjaCAodGhpcy5zaWduSW5NZXRob2QpIHtcbiAgICAgIGNhc2UgU2lnbkluTWV0aG9kLkVNQUlMX1BBU1NXT1JEOlxuICAgICAgICBjb25zdCByZXF1ZXN0OiBTaWduVXBSZXF1ZXN0ID0ge1xuICAgICAgICAgIGlkVG9rZW4sXG4gICAgICAgICAgcmV0dXJuU2VjdXJlVG9rZW46IHRydWUsXG4gICAgICAgICAgZW1haWw6IHRoaXMuX2VtYWlsLFxuICAgICAgICAgIHBhc3N3b3JkOiB0aGlzLl9wYXNzd29yZCxcbiAgICAgICAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgUmVjYXB0Y2hhQWN0aW9uTmFtZS5TSUdOX1VQX1BBU1NXT1JELFxuICAgICAgICAgIGxpbmtFbWFpbFBhc3N3b3JkLFxuICAgICAgICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICAgICAgICApO1xuICAgICAgY2FzZSBTaWduSW5NZXRob2QuRU1BSUxfTElOSzpcbiAgICAgICAgcmV0dXJuIHNpZ25JbldpdGhFbWFpbExpbmtGb3JMaW5raW5nKGF1dGgsIHtcbiAgICAgICAgICBpZFRva2VuLFxuICAgICAgICAgIGVtYWlsOiB0aGlzLl9lbWFpbCxcbiAgICAgICAgICBvb2JDb2RlOiB0aGlzLl9wYXNzd29yZFxuICAgICAgICB9KTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX2dldFJlYXV0aGVudGljYXRpb25SZXNvbHZlcihhdXRoOiBBdXRoSW50ZXJuYWwpOiBQcm9taXNlPElkVG9rZW5SZXNwb25zZT4ge1xuICAgIHJldHVybiB0aGlzLl9nZXRJZFRva2VuUmVzcG9uc2UoYXV0aCk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBFbmRwb2ludCxcbiAgSHR0cE1ldGhvZCxcbiAgX2FkZFRpZElmTmVjZXNzYXJ5LFxuICBfcGVyZm9ybVNpZ25JblJlcXVlc3Rcbn0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgSWRUb2tlbiwgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aElkcFJlcXVlc3Qge1xuICByZXF1ZXN0VXJpOiBzdHJpbmc7XG4gIHBvc3RCb2R5Pzogc3RyaW5nO1xuICBzZXNzaW9uSWQ/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICByZXR1cm5TZWN1cmVUb2tlbjogYm9vbGVhbjtcbiAgcmV0dXJuSWRwQ3JlZGVudGlhbD86IGJvb2xlYW47XG4gIGlkVG9rZW4/OiBJZFRva2VuO1xuICBhdXRvQ3JlYXRlPzogYm9vbGVhbjtcbiAgcGVuZGluZ1Rva2VuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhJZHBSZXNwb25zZSBleHRlbmRzIElkVG9rZW5SZXNwb25zZSB7XG4gIG9hdXRoQWNjZXNzVG9rZW4/OiBzdHJpbmc7XG4gIG9hdXRoVG9rZW5TZWNyZXQ/OiBzdHJpbmc7XG4gIG5vbmNlPzogc3RyaW5nO1xuICBvYXV0aElkVG9rZW4/OiBzdHJpbmc7XG4gIHBlbmRpbmdUb2tlbj86IHN0cmluZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbldpdGhJZHAoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25JbldpdGhJZHBSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhJZHBSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFNpZ25JbldpdGhJZHBSZXF1ZXN0LCBTaWduSW5XaXRoSWRwUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNJR05fSU5fV0lUSF9JRFAsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgcXVlcnlzdHJpbmcgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7XG4gIHNpZ25JbldpdGhJZHAsXG4gIFNpZ25JbldpdGhJZHBSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9pZHAnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2F1dGhfY3JlZGVudGlhbCc7XG5cbmNvbnN0IElEUF9SRVFVRVNUX1VSSSA9ICdodHRwOi8vbG9jYWxob3N0JztcblxuZXhwb3J0IGludGVyZmFjZSBPQXV0aENyZWRlbnRpYWxQYXJhbXMge1xuICAvLyBPQXV0aCAyIHVzZXMgZWl0aGVyIGlkIHRva2VuIG9yIGFjY2VzcyB0b2tlblxuICBpZFRva2VuPzogc3RyaW5nIHwgbnVsbDtcbiAgYWNjZXNzVG9rZW4/OiBzdHJpbmcgfCBudWxsO1xuXG4gIC8vIFRoZXNlIGZpZWxkcyBhcmUgdXNlZCB3aXRoIE9BdXRoIDFcbiAgb2F1dGhUb2tlbj86IHN0cmluZztcbiAgc2VjcmV0Pzogc3RyaW5nO1xuICBvYXV0aFRva2VuU2VjcmV0Pzogc3RyaW5nO1xuXG4gIC8vIE5vbmNlIGlzIG9ubHkgc2V0IGlmIHBlbmRpbmdUb2tlbiBpcyBub3QgcHJlc2VudFxuICBub25jZT86IHN0cmluZztcbiAgcGVuZGluZ1Rva2VuPzogc3RyaW5nO1xuXG4gIC8vIFV0aWxpdGllc1xuICBwcm92aWRlcklkOiBzdHJpbmc7XG4gIHNpZ25Jbk1ldGhvZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIE9BdXRoIGNyZWRlbnRpYWxzIHJldHVybmVkIGJ5IGFuIHtAbGluayBPQXV0aFByb3ZpZGVyfS5cbiAqXG4gKiBAcmVtYXJrc1xuICogSW1wbGVtZW50YXRpb25zIHNwZWNpZnkgdGhlIGRldGFpbHMgYWJvdXQgZWFjaCBhdXRoIHByb3ZpZGVyJ3MgY3JlZGVudGlhbCByZXF1aXJlbWVudHMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgT0F1dGhDcmVkZW50aWFsIGV4dGVuZHMgQXV0aENyZWRlbnRpYWwge1xuICAvKipcbiAgICogVGhlIE9BdXRoIElEIHRva2VuIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3JlZGVudGlhbCBpZiBpdCBiZWxvbmdzIHRvIGFuIE9JREMgcHJvdmlkZXIsXG4gICAqIHN1Y2ggYXMgYGdvb2dsZS5jb21gLlxuICAgKiBAcmVhZG9ubHlcbiAgICovXG4gIGlkVG9rZW4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgT0F1dGggYWNjZXNzIHRva2VuIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3JlZGVudGlhbCBpZiBpdCBiZWxvbmdzIHRvIGFuXG4gICAqIHtAbGluayBPQXV0aFByb3ZpZGVyfSwgc3VjaCBhcyBgZmFjZWJvb2suY29tYCwgYHR3aXR0ZXIuY29tYCwgZXRjLlxuICAgKiBAcmVhZG9ubHlcbiAgICovXG4gIGFjY2Vzc1Rva2VuPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIE9BdXRoIGFjY2VzcyB0b2tlbiBzZWNyZXQgYXNzb2NpYXRlZCB3aXRoIHRoZSBjcmVkZW50aWFsIGlmIGl0IGJlbG9uZ3MgdG8gYW4gT0F1dGggMS4wXG4gICAqIHByb3ZpZGVyLCBzdWNoIGFzIGB0d2l0dGVyLmNvbWAuXG4gICAqIEByZWFkb25seVxuICAgKi9cbiAgc2VjcmV0Pzogc3RyaW5nO1xuXG4gIHByaXZhdGUgbm9uY2U/OiBzdHJpbmc7XG4gIHByaXZhdGUgcGVuZGluZ1Rva2VuOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAvKiogQGludGVybmFsICovXG4gIHN0YXRpYyBfZnJvbVBhcmFtcyhwYXJhbXM6IE9BdXRoQ3JlZGVudGlhbFBhcmFtcyk6IE9BdXRoQ3JlZGVudGlhbCB7XG4gICAgY29uc3QgY3JlZCA9IG5ldyBPQXV0aENyZWRlbnRpYWwocGFyYW1zLnByb3ZpZGVySWQsIHBhcmFtcy5zaWduSW5NZXRob2QpO1xuXG4gICAgaWYgKHBhcmFtcy5pZFRva2VuIHx8IHBhcmFtcy5hY2Nlc3NUb2tlbikge1xuICAgICAgLy8gT0F1dGggMiBhbmQgZWl0aGVyIElEIHRva2VuIG9yIGFjY2VzcyB0b2tlbi5cbiAgICAgIGlmIChwYXJhbXMuaWRUb2tlbikge1xuICAgICAgICBjcmVkLmlkVG9rZW4gPSBwYXJhbXMuaWRUb2tlbjtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5hY2Nlc3NUb2tlbikge1xuICAgICAgICBjcmVkLmFjY2Vzc1Rva2VuID0gcGFyYW1zLmFjY2Vzc1Rva2VuO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgbm9uY2UgaWYgYXZhaWxhYmxlIGFuZCBubyBwZW5kaW5nVG9rZW4gaXMgcHJlc2VudC5cbiAgICAgIGlmIChwYXJhbXMubm9uY2UgJiYgIXBhcmFtcy5wZW5kaW5nVG9rZW4pIHtcbiAgICAgICAgY3JlZC5ub25jZSA9IHBhcmFtcy5ub25jZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5wZW5kaW5nVG9rZW4pIHtcbiAgICAgICAgY3JlZC5wZW5kaW5nVG9rZW4gPSBwYXJhbXMucGVuZGluZ1Rva2VuO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW1zLm9hdXRoVG9rZW4gJiYgcGFyYW1zLm9hdXRoVG9rZW5TZWNyZXQpIHtcbiAgICAgIC8vIE9BdXRoIDEgYW5kIE9BdXRoIHRva2VuIHdpdGggdG9rZW4gc2VjcmV0XG4gICAgICBjcmVkLmFjY2Vzc1Rva2VuID0gcGFyYW1zLm9hdXRoVG9rZW47XG4gICAgICBjcmVkLnNlY3JldCA9IHBhcmFtcy5vYXV0aFRva2VuU2VjcmV0O1xuICAgIH0gZWxzZSB7XG4gICAgICBfZmFpbChBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY3JlZDtcbiAgfVxuXG4gIC8qKiB7QGluaGVyaXRkb2MgQXV0aENyZWRlbnRpYWwudG9KU09OfSAgKi9cbiAgdG9KU09OKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkVG9rZW46IHRoaXMuaWRUb2tlbixcbiAgICAgIGFjY2Vzc1Rva2VuOiB0aGlzLmFjY2Vzc1Rva2VuLFxuICAgICAgc2VjcmV0OiB0aGlzLnNlY3JldCxcbiAgICAgIG5vbmNlOiB0aGlzLm5vbmNlLFxuICAgICAgcGVuZGluZ1Rva2VuOiB0aGlzLnBlbmRpbmdUb2tlbixcbiAgICAgIHByb3ZpZGVySWQ6IHRoaXMucHJvdmlkZXJJZCxcbiAgICAgIHNpZ25Jbk1ldGhvZDogdGhpcy5zaWduSW5NZXRob2RcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXRpYyBtZXRob2QgdG8gZGVzZXJpYWxpemUgYSBKU09OIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdCBpbnRvIGFuXG4gICAqIHtAbGluayAgQXV0aENyZWRlbnRpYWx9LlxuICAgKlxuICAgKiBAcGFyYW0ganNvbiAtIElucHV0IGNhbiBiZSBlaXRoZXIgT2JqZWN0IG9yIHRoZSBzdHJpbmdpZmllZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JqZWN0LlxuICAgKiBXaGVuIHN0cmluZyBpcyBwcm92aWRlZCwgSlNPTi5wYXJzZSB3b3VsZCBiZSBjYWxsZWQgZmlyc3QuXG4gICAqXG4gICAqIEByZXR1cm5zIElmIHRoZSBKU09OIGlucHV0IGRvZXMgbm90IHJlcHJlc2VudCBhbiB7QGxpbmsgIEF1dGhDcmVkZW50aWFsfSwgbnVsbCBpcyByZXR1cm5lZC5cbiAgICovXG4gIHN0YXRpYyBmcm9tSlNPTihqc29uOiBzdHJpbmcgfCBvYmplY3QpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICBjb25zdCBvYmogPSB0eXBlb2YganNvbiA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKGpzb24pIDoganNvbjtcbiAgICBjb25zdCB7IHByb3ZpZGVySWQsIHNpZ25Jbk1ldGhvZCwgLi4ucmVzdCB9OiBPQXV0aENyZWRlbnRpYWxQYXJhbXMgPSBvYmo7XG4gICAgaWYgKCFwcm92aWRlcklkIHx8ICFzaWduSW5NZXRob2QpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGNyZWQgPSBuZXcgT0F1dGhDcmVkZW50aWFsKHByb3ZpZGVySWQsIHNpZ25Jbk1ldGhvZCk7XG4gICAgY3JlZC5pZFRva2VuID0gcmVzdC5pZFRva2VuIHx8IHVuZGVmaW5lZDtcbiAgICBjcmVkLmFjY2Vzc1Rva2VuID0gcmVzdC5hY2Nlc3NUb2tlbiB8fCB1bmRlZmluZWQ7XG4gICAgY3JlZC5zZWNyZXQgPSByZXN0LnNlY3JldDtcbiAgICBjcmVkLm5vbmNlID0gcmVzdC5ub25jZTtcbiAgICBjcmVkLnBlbmRpbmdUb2tlbiA9IHJlc3QucGVuZGluZ1Rva2VuIHx8IG51bGw7XG4gICAgcmV0dXJuIGNyZWQ7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9nZXRJZFRva2VuUmVzcG9uc2UoYXV0aDogQXV0aEludGVybmFsKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QoKTtcbiAgICByZXR1cm4gc2lnbkluV2l0aElkcChhdXRoLCByZXF1ZXN0KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX2xpbmtUb0lkVG9rZW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPElkVG9rZW5SZXNwb25zZT4ge1xuICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLmJ1aWxkUmVxdWVzdCgpO1xuICAgIHJlcXVlc3QuaWRUb2tlbiA9IGlkVG9rZW47XG4gICAgcmV0dXJuIHNpZ25JbldpdGhJZHAoYXV0aCwgcmVxdWVzdCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9nZXRSZWF1dGhlbnRpY2F0aW9uUmVzb2x2ZXIoYXV0aDogQXV0aEludGVybmFsKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QoKTtcbiAgICByZXF1ZXN0LmF1dG9DcmVhdGUgPSBmYWxzZTtcbiAgICByZXR1cm4gc2lnbkluV2l0aElkcChhdXRoLCByZXF1ZXN0KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRSZXF1ZXN0KCk6IFNpZ25JbldpdGhJZHBSZXF1ZXN0IHtcbiAgICBjb25zdCByZXF1ZXN0OiBTaWduSW5XaXRoSWRwUmVxdWVzdCA9IHtcbiAgICAgIHJlcXVlc3RVcmk6IElEUF9SRVFVRVNUX1VSSSxcbiAgICAgIHJldHVyblNlY3VyZVRva2VuOiB0cnVlXG4gICAgfTtcblxuICAgIGlmICh0aGlzLnBlbmRpbmdUb2tlbikge1xuICAgICAgcmVxdWVzdC5wZW5kaW5nVG9rZW4gPSB0aGlzLnBlbmRpbmdUb2tlbjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcG9zdEJvZHk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGlmICh0aGlzLmlkVG9rZW4pIHtcbiAgICAgICAgcG9zdEJvZHlbJ2lkX3Rva2VuJ10gPSB0aGlzLmlkVG9rZW47XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5hY2Nlc3NUb2tlbikge1xuICAgICAgICBwb3N0Qm9keVsnYWNjZXNzX3Rva2VuJ10gPSB0aGlzLmFjY2Vzc1Rva2VuO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuc2VjcmV0KSB7XG4gICAgICAgIHBvc3RCb2R5WydvYXV0aF90b2tlbl9zZWNyZXQnXSA9IHRoaXMuc2VjcmV0O1xuICAgICAgfVxuXG4gICAgICBwb3N0Qm9keVsncHJvdmlkZXJJZCddID0gdGhpcy5wcm92aWRlcklkO1xuICAgICAgaWYgKHRoaXMubm9uY2UgJiYgIXRoaXMucGVuZGluZ1Rva2VuKSB7XG4gICAgICAgIHBvc3RCb2R5Wydub25jZSddID0gdGhpcy5ub25jZTtcbiAgICAgIH1cblxuICAgICAgcmVxdWVzdC5wb3N0Qm9keSA9IHF1ZXJ5c3RyaW5nKHBvc3RCb2R5KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEVuZHBvaW50LFxuICBIdHRwTWV0aG9kLFxuICBSZWNhcHRjaGFDbGllbnRUeXBlLFxuICBSZWNhcHRjaGFWZXJzaW9uLFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIF9tYWtlVGFnZ2VkRXJyb3IsXG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgX3BlcmZvcm1TaWduSW5SZXF1ZXN0XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi8uLi9jb3JlL2Vycm9ycyc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBTZXJ2ZXJFcnJvciwgU2VydmVyRXJyb3JNYXAgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlcXVlc3Qge1xuICBwaG9uZU51bWJlcjogc3RyaW5nO1xuICAvLyByZUNBUFRDSEEgdjIgdG9rZW5cbiAgcmVjYXB0Y2hhVG9rZW4/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICAvLyByZUNBUFRDSEEgRW50ZXJwcmlzZSB0b2tlblxuICBjYXB0Y2hhUmVzcG9uc2U/OiBzdHJpbmc7XG4gIGNsaWVudFR5cGU/OiBSZWNhcHRjaGFDbGllbnRUeXBlO1xuICByZWNhcHRjaGFWZXJzaW9uPzogUmVjYXB0Y2hhVmVyc2lvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZW5kUGhvbmVWZXJpZmljYXRpb25Db2RlUmVzcG9uc2Uge1xuICBzZXNzaW9uSW5mbzogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlcXVlc3Rcbik6IFByb21pc2U8U2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlcXVlc3QsXG4gICAgU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0VORF9WRVJJRklDQVRJT05fQ09ERSxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IHtcbiAgdGVtcG9yYXJ5UHJvb2Y/OiBzdHJpbmc7XG4gIHBob25lTnVtYmVyPzogc3RyaW5nO1xuICBzZXNzaW9uSW5mbz86IHN0cmluZztcbiAgY29kZT86IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlua1dpdGhQaG9uZU51bWJlclJlcXVlc3RcbiAgZXh0ZW5kcyBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IHtcbiAgaWRUb2tlbjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHtcbiAgdGVtcG9yYXJ5UHJvb2Y/OiBzdHJpbmc7XG4gIHBob25lTnVtYmVyPzogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aFBob25lTnVtYmVyKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybVNpZ25JblJlcXVlc3Q8XG4gICAgU2lnbkluV2l0aFBob25lTnVtYmVyUmVxdWVzdCxcbiAgICBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXNwb25zZVxuICA+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNJR05fSU5fV0lUSF9QSE9ORV9OVU1CRVIsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaW5rV2l0aFBob25lTnVtYmVyKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBMaW5rV2l0aFBob25lTnVtYmVyUmVxdWVzdFxuKTogUHJvbWlzZTxTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXNwb25zZT4ge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9wZXJmb3JtU2lnbkluUmVxdWVzdDxcbiAgICBMaW5rV2l0aFBob25lTnVtYmVyUmVxdWVzdCxcbiAgICBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXNwb25zZVxuICA+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNJR05fSU5fV0lUSF9QSE9ORV9OVU1CRVIsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG4gIGlmIChyZXNwb25zZS50ZW1wb3JhcnlQcm9vZikge1xuICAgIHRocm93IF9tYWtlVGFnZ2VkRXJyb3IoYXV0aCwgQXV0aEVycm9yQ29kZS5ORUVEX0NPTkZJUk1BVElPTiwgcmVzcG9uc2UpO1xuICB9XG4gIHJldHVybiByZXNwb25zZTtcbn1cblxuaW50ZXJmYWNlIFZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmdSZXF1ZXN0XG4gIGV4dGVuZHMgU2lnbkluV2l0aFBob25lTnVtYmVyUmVxdWVzdCB7XG4gIG9wZXJhdGlvbjogJ1JFQVVUSCc7XG59XG5cbmNvbnN0IFZFUklGWV9QSE9ORV9OVU1CRVJfRk9SX0VYSVNUSU5HX0VSUk9SX01BUF86IFBhcnRpYWw8XG4gIFNlcnZlckVycm9yTWFwPFNlcnZlckVycm9yPlxuPiA9IHtcbiAgW1NlcnZlckVycm9yLlVTRVJfTk9UX0ZPVU5EXTogQXV0aEVycm9yQ29kZS5VU0VSX0RFTEVURURcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlQaG9uZU51bWJlckZvckV4aXN0aW5nKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlPiB7XG4gIGNvbnN0IGFwaVJlcXVlc3Q6IFZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmdSZXF1ZXN0ID0ge1xuICAgIC4uLnJlcXVlc3QsXG4gICAgb3BlcmF0aW9uOiAnUkVBVVRIJ1xuICB9O1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFxuICAgIFZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmdSZXF1ZXN0LFxuICAgIFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9JTl9XSVRIX1BIT05FX05VTUJFUixcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgYXBpUmVxdWVzdCksXG4gICAgVkVSSUZZX1BIT05FX05VTUJFUl9GT1JfRVhJU1RJTkdfRVJST1JfTUFQX1xuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFByb3ZpZGVySWQsIFNpZ25Jbk1ldGhvZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuaW1wb3J0IHsgUGhvbmVPck9hdXRoVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9tZmEnO1xuaW1wb3J0IHtcbiAgbGlua1dpdGhQaG9uZU51bWJlcixcbiAgc2lnbkluV2l0aFBob25lTnVtYmVyLFxuICBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0LFxuICB2ZXJpZnlQaG9uZU51bWJlckZvckV4aXN0aW5nXG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9zbXMnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vYXV0aF9jcmVkZW50aWFsJztcblxuZXhwb3J0IGludGVyZmFjZSBQaG9uZUF1dGhDcmVkZW50aWFsUGFyYW1ldGVycyB7XG4gIHZlcmlmaWNhdGlvbklkPzogc3RyaW5nO1xuICB2ZXJpZmljYXRpb25Db2RlPzogc3RyaW5nO1xuICBwaG9uZU51bWJlcj86IHN0cmluZztcbiAgdGVtcG9yYXJ5UHJvb2Y/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgY3JlZGVudGlhbHMgcmV0dXJuZWQgYnkge0BsaW5rIFBob25lQXV0aFByb3ZpZGVyfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBQaG9uZUF1dGhDcmVkZW50aWFsIGV4dGVuZHMgQXV0aENyZWRlbnRpYWwge1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcGFyYW1zOiBQaG9uZUF1dGhDcmVkZW50aWFsUGFyYW1ldGVycykge1xuICAgIHN1cGVyKFByb3ZpZGVySWQuUEhPTkUsIFNpZ25Jbk1ldGhvZC5QSE9ORSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHN0YXRpYyBfZnJvbVZlcmlmaWNhdGlvbihcbiAgICB2ZXJpZmljYXRpb25JZDogc3RyaW5nLFxuICAgIHZlcmlmaWNhdGlvbkNvZGU6IHN0cmluZ1xuICApOiBQaG9uZUF1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gbmV3IFBob25lQXV0aENyZWRlbnRpYWwoeyB2ZXJpZmljYXRpb25JZCwgdmVyaWZpY2F0aW9uQ29kZSB9KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tVG9rZW5SZXNwb25zZShcbiAgICBwaG9uZU51bWJlcjogc3RyaW5nLFxuICAgIHRlbXBvcmFyeVByb29mOiBzdHJpbmdcbiAgKTogUGhvbmVBdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIG5ldyBQaG9uZUF1dGhDcmVkZW50aWFsKHsgcGhvbmVOdW1iZXIsIHRlbXBvcmFyeVByb29mIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8UGhvbmVPck9hdXRoVG9rZW5SZXNwb25zZT4ge1xuICAgIHJldHVybiBzaWduSW5XaXRoUGhvbmVOdW1iZXIoYXV0aCwgdGhpcy5fbWFrZVZlcmlmaWNhdGlvblJlcXVlc3QoKSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9saW5rVG9JZFRva2VuKFxuICAgIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBpZFRva2VuOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICByZXR1cm4gbGlua1dpdGhQaG9uZU51bWJlcihhdXRoLCB7XG4gICAgICBpZFRva2VuLFxuICAgICAgLi4udGhpcy5fbWFrZVZlcmlmaWNhdGlvblJlcXVlc3QoKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0UmVhdXRoZW50aWNhdGlvblJlc29sdmVyKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIHZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmcoYXV0aCwgdGhpcy5fbWFrZVZlcmlmaWNhdGlvblJlcXVlc3QoKSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9tYWtlVmVyaWZpY2F0aW9uUmVxdWVzdCgpOiBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IHtcbiAgICBjb25zdCB7IHRlbXBvcmFyeVByb29mLCBwaG9uZU51bWJlciwgdmVyaWZpY2F0aW9uSWQsIHZlcmlmaWNhdGlvbkNvZGUgfSA9XG4gICAgICB0aGlzLnBhcmFtcztcbiAgICBpZiAodGVtcG9yYXJ5UHJvb2YgJiYgcGhvbmVOdW1iZXIpIHtcbiAgICAgIHJldHVybiB7IHRlbXBvcmFyeVByb29mLCBwaG9uZU51bWJlciB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzZXNzaW9uSW5mbzogdmVyaWZpY2F0aW9uSWQsXG4gICAgICBjb2RlOiB2ZXJpZmljYXRpb25Db2RlXG4gICAgfTtcbiAgfVxuXG4gIC8qKiB7QGluaGVyaXRkb2MgQXV0aENyZWRlbnRpYWwudG9KU09OfSAqL1xuICB0b0pTT04oKTogb2JqZWN0IHtcbiAgICBjb25zdCBvYmo6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBwcm92aWRlcklkOiB0aGlzLnByb3ZpZGVySWRcbiAgICB9O1xuICAgIGlmICh0aGlzLnBhcmFtcy5waG9uZU51bWJlcikge1xuICAgICAgb2JqLnBob25lTnVtYmVyID0gdGhpcy5wYXJhbXMucGhvbmVOdW1iZXI7XG4gICAgfVxuICAgIGlmICh0aGlzLnBhcmFtcy50ZW1wb3JhcnlQcm9vZikge1xuICAgICAgb2JqLnRlbXBvcmFyeVByb29mID0gdGhpcy5wYXJhbXMudGVtcG9yYXJ5UHJvb2Y7XG4gICAgfVxuICAgIGlmICh0aGlzLnBhcmFtcy52ZXJpZmljYXRpb25Db2RlKSB7XG4gICAgICBvYmoudmVyaWZpY2F0aW9uQ29kZSA9IHRoaXMucGFyYW1zLnZlcmlmaWNhdGlvbkNvZGU7XG4gICAgfVxuICAgIGlmICh0aGlzLnBhcmFtcy52ZXJpZmljYXRpb25JZCkge1xuICAgICAgb2JqLnZlcmlmaWNhdGlvbklkID0gdGhpcy5wYXJhbXMudmVyaWZpY2F0aW9uSWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIC8qKiBHZW5lcmF0ZXMgYSBwaG9uZSBjcmVkZW50aWFsIGJhc2VkIG9uIGEgcGxhaW4gb2JqZWN0IG9yIGEgSlNPTiBzdHJpbmcuICovXG4gIHN0YXRpYyBmcm9tSlNPTihqc29uOiBvYmplY3QgfCBzdHJpbmcpOiBQaG9uZUF1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgaWYgKHR5cGVvZiBqc29uID09PSAnc3RyaW5nJykge1xuICAgICAganNvbiA9IEpTT04ucGFyc2UoanNvbik7XG4gICAgfVxuXG4gICAgY29uc3QgeyB2ZXJpZmljYXRpb25JZCwgdmVyaWZpY2F0aW9uQ29kZSwgcGhvbmVOdW1iZXIsIHRlbXBvcmFyeVByb29mIH0gPVxuICAgICAganNvbiBhcyB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICAgIGlmIChcbiAgICAgICF2ZXJpZmljYXRpb25Db2RlICYmXG4gICAgICAhdmVyaWZpY2F0aW9uSWQgJiZcbiAgICAgICFwaG9uZU51bWJlciAmJlxuICAgICAgIXRlbXBvcmFyeVByb29mXG4gICAgKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFBob25lQXV0aENyZWRlbnRpYWwoe1xuICAgICAgdmVyaWZpY2F0aW9uSWQsXG4gICAgICB2ZXJpZmljYXRpb25Db2RlLFxuICAgICAgcGhvbmVOdW1iZXIsXG4gICAgICB0ZW1wb3JhcnlQcm9vZlxuICAgIH0pO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgZXh0cmFjdFF1ZXJ5c3RyaW5nLCBxdWVyeXN0cmluZ0RlY29kZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEFjdGlvbkNvZGVPcGVyYXRpb24gfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuL3V0aWwvYXNzZXJ0JztcblxuLyoqXG4gKiBFbnVtcyBmb3IgZmllbGRzIGluIFVSTCBxdWVyeSBzdHJpbmcuXG4gKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuY29uc3QgZW51bSBRdWVyeUZpZWxkIHtcbiAgQVBJX0tFWSA9ICdhcGlLZXknLFxuICBDT0RFID0gJ29vYkNvZGUnLFxuICBDT05USU5VRV9VUkwgPSAnY29udGludWVVcmwnLFxuICBMQU5HVUFHRV9DT0RFID0gJ2xhbmcnLFxuICBNT0RFID0gJ21vZGUnLFxuICBURU5BTlRfSUQgPSAndGVuYW50SWQnXG59XG5cbi8qKlxuICogTWFwcyB0aGUgbW9kZSBzdHJpbmcgaW4gYWN0aW9uIGNvZGUgVVJMIHRvIEFjdGlvbiBDb2RlIEluZm8gb3BlcmF0aW9uLlxuICpcbiAqIEBwYXJhbSBtb2RlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlTW9kZShtb2RlOiBzdHJpbmcgfCBudWxsKTogQWN0aW9uQ29kZU9wZXJhdGlvbiB8IG51bGwge1xuICBzd2l0Y2ggKG1vZGUpIHtcbiAgICBjYXNlICdyZWNvdmVyRW1haWwnOlxuICAgICAgcmV0dXJuIEFjdGlvbkNvZGVPcGVyYXRpb24uUkVDT1ZFUl9FTUFJTDtcbiAgICBjYXNlICdyZXNldFBhc3N3b3JkJzpcbiAgICAgIHJldHVybiBBY3Rpb25Db2RlT3BlcmF0aW9uLlBBU1NXT1JEX1JFU0VUO1xuICAgIGNhc2UgJ3NpZ25Jbic6XG4gICAgICByZXR1cm4gQWN0aW9uQ29kZU9wZXJhdGlvbi5FTUFJTF9TSUdOSU47XG4gICAgY2FzZSAndmVyaWZ5RW1haWwnOlxuICAgICAgcmV0dXJuIEFjdGlvbkNvZGVPcGVyYXRpb24uVkVSSUZZX0VNQUlMO1xuICAgIGNhc2UgJ3ZlcmlmeUFuZENoYW5nZUVtYWlsJzpcbiAgICAgIHJldHVybiBBY3Rpb25Db2RlT3BlcmF0aW9uLlZFUklGWV9BTkRfQ0hBTkdFX0VNQUlMO1xuICAgIGNhc2UgJ3JldmVydFNlY29uZEZhY3RvckFkZGl0aW9uJzpcbiAgICAgIHJldHVybiBBY3Rpb25Db2RlT3BlcmF0aW9uLlJFVkVSVF9TRUNPTkRfRkFDVE9SX0FERElUSU9OO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vKipcbiAqIEhlbHBlciB0byBwYXJzZSBGREwgbGlua3NcbiAqXG4gKiBAcGFyYW0gdXJsXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRGVlcExpbmsodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBsaW5rID0gcXVlcnlzdHJpbmdEZWNvZGUoZXh0cmFjdFF1ZXJ5c3RyaW5nKHVybCkpWydsaW5rJ107XG5cbiAgLy8gRG91YmxlIGxpbmsgY2FzZSAoYXV0b21hdGljIHJlZGlyZWN0KS5cbiAgY29uc3QgZG91YmxlRGVlcExpbmsgPSBsaW5rXG4gICAgPyBxdWVyeXN0cmluZ0RlY29kZShleHRyYWN0UXVlcnlzdHJpbmcobGluaykpWydkZWVwX2xpbmtfaWQnXVxuICAgIDogbnVsbDtcbiAgLy8gaU9TIGN1c3RvbSBzY2hlbWUgbGlua3MuXG4gIGNvbnN0IGlPU0RlZXBMaW5rID0gcXVlcnlzdHJpbmdEZWNvZGUoZXh0cmFjdFF1ZXJ5c3RyaW5nKHVybCkpW1xuICAgICdkZWVwX2xpbmtfaWQnXG4gIF07XG4gIGNvbnN0IGlPU0RvdWJsZURlZXBMaW5rID0gaU9TRGVlcExpbmtcbiAgICA/IHF1ZXJ5c3RyaW5nRGVjb2RlKGV4dHJhY3RRdWVyeXN0cmluZyhpT1NEZWVwTGluaykpWydsaW5rJ11cbiAgICA6IG51bGw7XG4gIHJldHVybiBpT1NEb3VibGVEZWVwTGluayB8fCBpT1NEZWVwTGluayB8fCBkb3VibGVEZWVwTGluayB8fCBsaW5rIHx8IHVybDtcbn1cblxuLyoqXG4gKiBBIHV0aWxpdHkgY2xhc3MgdG8gcGFyc2UgZW1haWwgYWN0aW9uIFVSTHMgc3VjaCBhcyBwYXNzd29yZCByZXNldCwgZW1haWwgdmVyaWZpY2F0aW9uLFxuICogZW1haWwgbGluayBzaWduIGluLCBldGMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgQWN0aW9uQ29kZVVSTCB7XG4gIC8qKlxuICAgKiBUaGUgQVBJIGtleSBvZiB0aGUgZW1haWwgYWN0aW9uIGxpbmsuXG4gICAqL1xuICByZWFkb25seSBhcGlLZXk6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBhY3Rpb24gY29kZSBvZiB0aGUgZW1haWwgYWN0aW9uIGxpbmsuXG4gICAqL1xuICByZWFkb25seSBjb2RlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgY29udGludWUgVVJMIG9mIHRoZSBlbWFpbCBhY3Rpb24gbGluay4gTnVsbCBpZiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSBjb250aW51ZVVybDogc3RyaW5nIHwgbnVsbDtcbiAgLyoqXG4gICAqIFRoZSBsYW5ndWFnZSBjb2RlIG9mIHRoZSBlbWFpbCBhY3Rpb24gbGluay4gTnVsbCBpZiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSBsYW5ndWFnZUNvZGU6IHN0cmluZyB8IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgYWN0aW9uIHBlcmZvcm1lZCBieSB0aGUgZW1haWwgYWN0aW9uIGxpbmsuIEl0IHJldHVybnMgZnJvbSBvbmUgb2YgdGhlIHR5cGVzIGZyb21cbiAgICoge0BsaW5rIEFjdGlvbkNvZGVJbmZvfVxuICAgKi9cbiAgcmVhZG9ubHkgb3BlcmF0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdGVuYW50IElEIG9mIHRoZSBlbWFpbCBhY3Rpb24gbGluay4gTnVsbCBpZiB0aGUgZW1haWwgYWN0aW9uIGlzIGZyb20gdGhlIHBhcmVudCBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgdGVuYW50SWQ6IHN0cmluZyB8IG51bGw7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBhY3Rpb25MaW5rIC0gVGhlIGxpbmsgZnJvbSB3aGljaCB0byBleHRyYWN0IHRoZSBVUkwuXG4gICAqIEByZXR1cm5zIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVVSTH0gb2JqZWN0LCBvciBudWxsIGlmIHRoZSBsaW5rIGlzIGludmFsaWQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgY29uc3RydWN0b3IoYWN0aW9uTGluazogc3RyaW5nKSB7XG4gICAgY29uc3Qgc2VhcmNoUGFyYW1zID0gcXVlcnlzdHJpbmdEZWNvZGUoZXh0cmFjdFF1ZXJ5c3RyaW5nKGFjdGlvbkxpbmspKTtcbiAgICBjb25zdCBhcGlLZXkgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5BUElfS0VZXSA/PyBudWxsO1xuICAgIGNvbnN0IGNvZGUgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5DT0RFXSA/PyBudWxsO1xuICAgIGNvbnN0IG9wZXJhdGlvbiA9IHBhcnNlTW9kZShzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5NT0RFXSA/PyBudWxsKTtcbiAgICAvLyBWYWxpZGF0ZSBBUEkga2V5LCBjb2RlIGFuZCBtb2RlLlxuICAgIF9hc3NlcnQoYXBpS2V5ICYmIGNvZGUgJiYgb3BlcmF0aW9uLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICB0aGlzLmFwaUtleSA9IGFwaUtleTtcbiAgICB0aGlzLm9wZXJhdGlvbiA9IG9wZXJhdGlvbjtcbiAgICB0aGlzLmNvZGUgPSBjb2RlO1xuICAgIHRoaXMuY29udGludWVVcmwgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5DT05USU5VRV9VUkxdID8/IG51bGw7XG4gICAgdGhpcy5sYW5ndWFnZUNvZGUgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5MQU5HVUFHRV9DT0RFXSA/PyBudWxsO1xuICAgIHRoaXMudGVuYW50SWQgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5URU5BTlRfSURdID8/IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSBlbWFpbCBhY3Rpb24gbGluayBzdHJpbmcgYW5kIHJldHVybnMgYW4ge0BsaW5rIEFjdGlvbkNvZGVVUkx9IGlmIHRoZSBsaW5rIGlzIHZhbGlkLFxuICAgKiBvdGhlcndpc2UgcmV0dXJucyBudWxsLlxuICAgKlxuICAgKiBAcGFyYW0gbGluayAgLSBUaGUgZW1haWwgYWN0aW9uIGxpbmsgc3RyaW5nLlxuICAgKiBAcmV0dXJucyBUaGUge0BsaW5rIEFjdGlvbkNvZGVVUkx9IG9iamVjdCwgb3IgbnVsbCBpZiB0aGUgbGluayBpcyBpbnZhbGlkLlxuICAgKlxuICAgKiBAcHVibGljXG4gICAqL1xuICBzdGF0aWMgcGFyc2VMaW5rKGxpbms6IHN0cmluZyk6IEFjdGlvbkNvZGVVUkwgfCBudWxsIHtcbiAgICBjb25zdCBhY3Rpb25MaW5rID0gcGFyc2VEZWVwTGluayhsaW5rKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIG5ldyBBY3Rpb25Db2RlVVJMKGFjdGlvbkxpbmspO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUGFyc2VzIHRoZSBlbWFpbCBhY3Rpb24gbGluayBzdHJpbmcgYW5kIHJldHVybnMgYW4ge0BsaW5rIEFjdGlvbkNvZGVVUkx9IGlmXG4gKiB0aGUgbGluayBpcyB2YWxpZCwgb3RoZXJ3aXNlIHJldHVybnMgbnVsbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFjdGlvbkNvZGVVUkwobGluazogc3RyaW5nKTogQWN0aW9uQ29kZVVSTCB8IG51bGwge1xuICByZXR1cm4gQWN0aW9uQ29kZVVSTC5wYXJzZUxpbmsobGluayk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUHJvdmlkZXJJZCwgU2lnbkluTWV0aG9kIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgQWN0aW9uQ29kZVVSTCB9IGZyb20gJy4uL2FjdGlvbl9jb2RlX3VybCc7XG5pbXBvcnQgeyBFbWFpbEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvZW1haWwnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBfYXNzZXJ0IH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBnZW5lcmF0aW5nIHtAbGluayBFbWFpbEF1dGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBFbWFpbEF1dGhQcm92aWRlciBpbXBsZW1lbnRzIEF1dGhQcm92aWRlciB7XG4gIC8qKlxuICAgKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5QQVNTV09SRCwgZXZlbiBmb3IgZW1haWwgbGluay5cbiAgICovXG4gIHN0YXRpYyByZWFkb25seSBQUk9WSURFUl9JRDogJ3Bhc3N3b3JkJyA9IFByb3ZpZGVySWQuUEFTU1dPUkQ7XG4gIC8qKlxuICAgKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX1BBU1NXT1JELlxuICAgKi9cbiAgc3RhdGljIHJlYWRvbmx5IEVNQUlMX1BBU1NXT1JEX1NJR05fSU5fTUVUSE9EOiAncGFzc3dvcmQnID1cbiAgICBTaWduSW5NZXRob2QuRU1BSUxfUEFTU1dPUkQ7XG4gIC8qKlxuICAgKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX0xJTksuXG4gICAqL1xuICBzdGF0aWMgcmVhZG9ubHkgRU1BSUxfTElOS19TSUdOX0lOX01FVEhPRDogJ2VtYWlsTGluaycgPVxuICAgIFNpZ25Jbk1ldGhvZC5FTUFJTF9MSU5LO1xuICAvKipcbiAgICogQWx3YXlzIHNldCB0byB7QGxpbmsgUHJvdmlkZXJJZH0uUEFTU1dPUkQsIGV2ZW4gZm9yIGVtYWlsIGxpbmsuXG4gICAqL1xuICByZWFkb25seSBwcm92aWRlcklkID0gRW1haWxBdXRoUHJvdmlkZXIuUFJPVklERVJfSUQ7XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgYW4ge0BsaW5rIEF1dGhDcmVkZW50aWFsfSB1c2luZyBhbiBlbWFpbCBhbmQgcGFzc3dvcmQuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGphdmFzY3JpcHRcbiAgICogY29uc3QgYXV0aENyZWRlbnRpYWwgPSBFbWFpbEF1dGhQcm92aWRlci5jcmVkZW50aWFsKGVtYWlsLCBwYXNzd29yZCk7XG4gICAqIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgc2lnbkluV2l0aENyZWRlbnRpYWwoYXV0aCwgYXV0aENyZWRlbnRpYWwpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgamF2YXNjcmlwdFxuICAgKiBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IHNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkKGF1dGgsIGVtYWlsLCBwYXNzd29yZCk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAcGFyYW0gZW1haWwgLSBFbWFpbCBhZGRyZXNzLlxuICAgKiBAcGFyYW0gcGFzc3dvcmQgLSBVc2VyIGFjY291bnQgcGFzc3dvcmQuXG4gICAqIEByZXR1cm5zIFRoZSBhdXRoIHByb3ZpZGVyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbChlbWFpbDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogRW1haWxBdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIEVtYWlsQXV0aENyZWRlbnRpYWwuX2Zyb21FbWFpbEFuZFBhc3N3b3JkKGVtYWlsLCBwYXNzd29yZCk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBhbiB7QGxpbmsgQXV0aENyZWRlbnRpYWx9IHVzaW5nIGFuIGVtYWlsIGFuZCBhbiBlbWFpbCBsaW5rIGFmdGVyIGEgc2lnbiBpbiB3aXRoXG4gICAqIGVtYWlsIGxpbmsgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqYXZhc2NyaXB0XG4gICAqIGNvbnN0IGF1dGhDcmVkZW50aWFsID0gRW1haWxBdXRoUHJvdmlkZXIuY3JlZGVudGlhbFdpdGhMaW5rKGF1dGgsIGVtYWlsLCBlbWFpbExpbmspO1xuICAgKiBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IHNpZ25JbldpdGhDcmVkZW50aWFsKGF1dGgsIGF1dGhDcmVkZW50aWFsKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGphdmFzY3JpcHRcbiAgICogYXdhaXQgc2VuZFNpZ25JbkxpbmtUb0VtYWlsKGF1dGgsIGVtYWlsKTtcbiAgICogLy8gT2J0YWluIGVtYWlsTGluayBmcm9tIHVzZXIuXG4gICAqIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgc2lnbkluV2l0aEVtYWlsTGluayhhdXRoLCBlbWFpbCwgZW1haWxMaW5rKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZSB1c2VkIHRvIHZlcmlmeSB0aGUgbGluay5cbiAgICogQHBhcmFtIGVtYWlsIC0gRW1haWwgYWRkcmVzcy5cbiAgICogQHBhcmFtIGVtYWlsTGluayAtIFNpZ24taW4gZW1haWwgbGluay5cbiAgICogQHJldHVybnMgLSBUaGUgYXV0aCBwcm92aWRlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxXaXRoTGluayhcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGVtYWlsTGluazogc3RyaW5nXG4gICk6IEVtYWlsQXV0aENyZWRlbnRpYWwge1xuICAgIGNvbnN0IGFjdGlvbkNvZGVVcmwgPSBBY3Rpb25Db2RlVVJMLnBhcnNlTGluayhlbWFpbExpbmspO1xuICAgIF9hc3NlcnQoYWN0aW9uQ29kZVVybCwgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUik7XG5cbiAgICByZXR1cm4gRW1haWxBdXRoQ3JlZGVudGlhbC5fZnJvbUVtYWlsQW5kQ29kZShcbiAgICAgIGVtYWlsLFxuICAgICAgYWN0aW9uQ29kZVVybC5jb2RlLFxuICAgICAgYWN0aW9uQ29kZVVybC50ZW5hbnRJZFxuICAgICk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoUHJvdmlkZXIgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG4vKipcbiAqIE1hcCBvZiBPQXV0aCBDdXN0b20gUGFyYW1ldGVycy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCB0eXBlIEN1c3RvbVBhcmFtZXRlcnMgPSBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4vKipcbiAqIFRoZSBiYXNlIGNsYXNzIGZvciBhbGwgRmVkZXJhdGVkIHByb3ZpZGVycyAoT0F1dGggKGluY2x1ZGluZyBPSURDKSwgU0FNTCkuXG4gKlxuICogVGhpcyBjbGFzcyBpcyBub3QgbWVhbnQgdG8gYmUgaW5zdGFudGlhdGVkIGRpcmVjdGx5LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEZlZGVyYXRlZEF1dGhQcm92aWRlciBpbXBsZW1lbnRzIEF1dGhQcm92aWRlciB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgZGVmYXVsdExhbmd1YWdlQ29kZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBjdXN0b21QYXJhbWV0ZXJzOiBDdXN0b21QYXJhbWV0ZXJzID0ge307XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yIGZvciBnZW5lcmljIE9BdXRoIHByb3ZpZGVycy5cbiAgICpcbiAgICogQHBhcmFtIHByb3ZpZGVySWQgLSBQcm92aWRlciBmb3Igd2hpY2ggY3JlZGVudGlhbHMgc2hvdWxkIGJlIGdlbmVyYXRlZC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHByb3ZpZGVySWQ6IHN0cmluZykge31cblxuICAvKipcbiAgICogU2V0IHRoZSBsYW5ndWFnZSBnb2RlLlxuICAgKlxuICAgKiBAcGFyYW0gbGFuZ3VhZ2VDb2RlIC0gbGFuZ3VhZ2UgY29kZVxuICAgKi9cbiAgc2V0RGVmYXVsdExhbmd1YWdlKGxhbmd1YWdlQ29kZTogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuZGVmYXVsdExhbmd1YWdlQ29kZSA9IGxhbmd1YWdlQ29kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBPQXV0aCBjdXN0b20gcGFyYW1ldGVycyB0byBwYXNzIGluIGFuIE9BdXRoIHJlcXVlc3QgZm9yIHBvcHVwIGFuZCByZWRpcmVjdCBzaWduLWluXG4gICAqIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEZvciBhIGRldGFpbGVkIGxpc3QsIGNoZWNrIHRoZSByZXNlcnZlZCByZXF1aXJlZCBPQXV0aCAyLjAgcGFyYW1ldGVycyBzdWNoIGFzIGBjbGllbnRfaWRgLFxuICAgKiBgcmVkaXJlY3RfdXJpYCwgYHNjb3BlYCwgYHJlc3BvbnNlX3R5cGVgLCBhbmQgYHN0YXRlYCBhcmUgbm90IGFsbG93ZWQgYW5kIHdpbGwgYmUgaWdub3JlZC5cbiAgICpcbiAgICogQHBhcmFtIGN1c3RvbU9BdXRoUGFyYW1ldGVycyAtIFRoZSBjdXN0b20gT0F1dGggcGFyYW1ldGVycyB0byBwYXNzIGluIHRoZSBPQXV0aCByZXF1ZXN0LlxuICAgKi9cbiAgc2V0Q3VzdG9tUGFyYW1ldGVycyhjdXN0b21PQXV0aFBhcmFtZXRlcnM6IEN1c3RvbVBhcmFtZXRlcnMpOiBBdXRoUHJvdmlkZXIge1xuICAgIHRoaXMuY3VzdG9tUGFyYW1ldGVycyA9IGN1c3RvbU9BdXRoUGFyYW1ldGVycztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZSB0aGUgY3VycmVudCBsaXN0IG9mIHtAbGluayBDdXN0b21QYXJhbWV0ZXJzfS5cbiAgICovXG4gIGdldEN1c3RvbVBhcmFtZXRlcnMoKTogQ3VzdG9tUGFyYW1ldGVycyB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tUGFyYW1ldGVycztcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEF1dGhQcm92aWRlciwgVXNlckNyZWRlbnRpYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQgeyBfYXNzZXJ0IH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbmltcG9ydCB7IE9BdXRoQ3JlZGVudGlhbCwgT0F1dGhDcmVkZW50aWFsUGFyYW1zIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvb2F1dGgnO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgU2lnbkluV2l0aElkcFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vLi4vaW50ZXJuYWwnO1xuaW1wb3J0IHsgRmVkZXJhdGVkQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi9mZWRlcmF0ZWQnO1xuXG4vKipcbiAqIERlZmluZXMgdGhlIG9wdGlvbnMgZm9yIGluaXRpYWxpemluZyBhbiB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAcmVtYXJrc1xuICogRm9yIElEIHRva2VucyB3aXRoIG5vbmNlIGNsYWltLCB0aGUgcmF3IG5vbmNlIGhhcyB0byBhbHNvIGJlIHByb3ZpZGVkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPQXV0aENyZWRlbnRpYWxPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBPQXV0aCBJRCB0b2tlbiB1c2VkIHRvIGluaXRpYWxpemUgdGhlIHtAbGluayBPQXV0aENyZWRlbnRpYWx9LlxuICAgKi9cbiAgaWRUb2tlbj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBPQXV0aCBhY2Nlc3MgdG9rZW4gdXNlZCB0byBpbml0aWFsaXplIHRoZSB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfS5cbiAgICovXG4gIGFjY2Vzc1Rva2VuPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHJhdyBub25jZSBhc3NvY2lhdGVkIHdpdGggdGhlIElEIHRva2VuLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJdCBpcyByZXF1aXJlZCB3aGVuIGFuIElEIHRva2VuIHdpdGggYSBub25jZSBmaWVsZCBpcyBwcm92aWRlZC4gVGhlIFNIQS0yNTYgaGFzaCBvZiB0aGVcbiAgICogcmF3IG5vbmNlIG11c3QgbWF0Y2ggdGhlIG5vbmNlIGZpZWxkIGluIHRoZSBJRCB0b2tlbi5cbiAgICovXG4gIHJhd05vbmNlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbW1vbiBjb2RlIHRvIGFsbCBPQXV0aCBwcm92aWRlcnMuIFRoaXMgaXMgc2VwYXJhdGUgZnJvbSB0aGVcbiAqIHtAbGluayBPQXV0aFByb3ZpZGVyfSBzbyB0aGF0IGNoaWxkIHByb3ZpZGVycyAobGlrZVxuICoge0BsaW5rIEdvb2dsZUF1dGhQcm92aWRlcn0pIGRvbid0IGluaGVyaXQgdGhlIGBjcmVkZW50aWFsYCBpbnN0YW5jZSBtZXRob2QuXG4gKiBJbnN0ZWFkLCB0aGV5IHJlbHkgb24gYSBzdGF0aWMgYGNyZWRlbnRpYWxgIG1ldGhvZC5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VPQXV0aFByb3ZpZGVyXG4gIGV4dGVuZHMgRmVkZXJhdGVkQXV0aFByb3ZpZGVyXG4gIGltcGxlbWVudHMgQXV0aFByb3ZpZGVyXG57XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBzY29wZXM6IHN0cmluZ1tdID0gW107XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBPQXV0aCBzY29wZSB0byB0aGUgY3JlZGVudGlhbC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gUHJvdmlkZXIgT0F1dGggc2NvcGUgdG8gYWRkLlxuICAgKi9cbiAgYWRkU2NvcGUoc2NvcGU6IHN0cmluZyk6IEF1dGhQcm92aWRlciB7XG4gICAgLy8gSWYgbm90IGFscmVhZHkgYWRkZWQsIGFkZCBzY29wZSB0byBsaXN0LlxuICAgIGlmICghdGhpcy5zY29wZXMuaW5jbHVkZXMoc2NvcGUpKSB7XG4gICAgICB0aGlzLnNjb3Blcy5wdXNoKHNjb3BlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgdGhlIGN1cnJlbnQgbGlzdCBvZiBPQXV0aCBzY29wZXMuXG4gICAqL1xuICBnZXRTY29wZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5zY29wZXNdO1xuICB9XG59XG5cbi8qKlxuICogUHJvdmlkZXIgZm9yIGdlbmVyYXRpbmcgZ2VuZXJpYyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHJlZGlyZWN0LlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgT0F1dGhQcm92aWRlcignZ29vZ2xlLmNvbScpO1xuICogLy8gU3RhcnQgYSBzaWduIGluIHByb2Nlc3MgZm9yIGFuIHVuYXV0aGVudGljYXRlZCB1c2VyLlxuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdlbWFpbCcpO1xuICogYXdhaXQgc2lnbkluV2l0aFJlZGlyZWN0KGF1dGgsIHByb3ZpZGVyKTtcbiAqIC8vIFRoaXMgd2lsbCB0cmlnZ2VyIGEgZnVsbCBwYWdlIHJlZGlyZWN0IGF3YXkgZnJvbSB5b3VyIGFwcFxuICpcbiAqIC8vIEFmdGVyIHJldHVybmluZyBmcm9tIHRoZSByZWRpcmVjdCB3aGVuIHlvdXIgYXBwIGluaXRpYWxpemVzIHlvdSBjYW4gb2J0YWluIHRoZSByZXN1bHRcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldFJlZGlyZWN0UmVzdWx0KGF1dGgpO1xuICogaWYgKHJlc3VsdCkge1xuICogICAvLyBUaGlzIGlzIHRoZSBzaWduZWQtaW4gdXNlclxuICogICBjb25zdCB1c2VyID0gcmVzdWx0LnVzZXI7XG4gKiAgIC8vIFRoaXMgZ2l2ZXMgeW91IGEgT0F1dGggQWNjZXNzIFRva2VuIGZvciB0aGUgcHJvdmlkZXIuXG4gKiAgIGNvbnN0IGNyZWRlbnRpYWwgPSBwcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChhdXRoLCByZXN1bHQpO1xuICogICBjb25zdCB0b2tlbiA9IGNyZWRlbnRpYWwuYWNjZXNzVG9rZW47XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHBvcHVwLlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgT0F1dGhQcm92aWRlcignZ29vZ2xlLmNvbScpO1xuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdlbWFpbCcpO1xuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgc2lnbkluV2l0aFBvcHVwKGF1dGgsIHByb3ZpZGVyKTtcbiAqXG4gKiAvLyBUaGUgc2lnbmVkLWluIHVzZXIgaW5mby5cbiAqIGNvbnN0IHVzZXIgPSByZXN1bHQudXNlcjtcbiAqIC8vIFRoaXMgZ2l2ZXMgeW91IGEgT0F1dGggQWNjZXNzIFRva2VuIGZvciB0aGUgcHJvdmlkZXIuXG4gKiBjb25zdCBjcmVkZW50aWFsID0gcHJvdmlkZXIuY3JlZGVudGlhbEZyb21SZXN1bHQoYXV0aCwgcmVzdWx0KTtcbiAqIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqIGBgYFxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgT0F1dGhQcm92aWRlciBleHRlbmRzIEJhc2VPQXV0aFByb3ZpZGVyIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4ge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIEpTT04gc3RyaW5nIG9yIGEgcGxhaW4gb2JqZWN0LlxuICAgKiBAcGFyYW0ganNvbiAtIEEgcGxhaW4gb2JqZWN0IG9yIGEgSlNPTiBzdHJpbmdcbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbUpTT04oanNvbjogb2JqZWN0IHwgc3RyaW5nKTogT0F1dGhDcmVkZW50aWFsIHtcbiAgICBjb25zdCBvYmogPSB0eXBlb2YganNvbiA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKGpzb24pIDoganNvbjtcbiAgICBfYXNzZXJ0KFxuICAgICAgJ3Byb3ZpZGVySWQnIGluIG9iaiAmJiAnc2lnbkluTWV0aG9kJyBpbiBvYmosXG4gICAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICAgKTtcbiAgICByZXR1cm4gT0F1dGhDcmVkZW50aWFsLl9mcm9tUGFyYW1zKG9iaik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSBnZW5lcmljIE9BdXRoIHByb3ZpZGVyJ3MgYWNjZXNzIHRva2VuIG9yIElEIHRva2VuLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBUaGUgcmF3IG5vbmNlIGlzIHJlcXVpcmVkIHdoZW4gYW4gSUQgdG9rZW4gd2l0aCBhIG5vbmNlIGZpZWxkIGlzIHByb3ZpZGVkLiBUaGUgU0hBLTI1NiBoYXNoIG9mXG4gICAqIHRoZSByYXcgbm9uY2UgbXVzdCBtYXRjaCB0aGUgbm9uY2UgZmllbGQgaW4gdGhlIElEIHRva2VuLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqYXZhc2NyaXB0XG4gICAqIC8vIGBnb29nbGVVc2VyYCBmcm9tIHRoZSBvbnN1Y2Nlc3MgR29vZ2xlIFNpZ24gSW4gY2FsbGJhY2suXG4gICAqIC8vIEluaXRpYWxpemUgYSBnZW5lcmF0ZSBPQXV0aCBwcm92aWRlciB3aXRoIGEgYGdvb2dsZS5jb21gIHByb3ZpZGVySWQuXG4gICAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IE9BdXRoUHJvdmlkZXIoJ2dvb2dsZS5jb20nKTtcbiAgICogY29uc3QgY3JlZGVudGlhbCA9IHByb3ZpZGVyLmNyZWRlbnRpYWwoe1xuICAgKiAgIGlkVG9rZW46IGdvb2dsZVVzZXIuZ2V0QXV0aFJlc3BvbnNlKCkuaWRfdG9rZW4sXG4gICAqIH0pO1xuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoQ3JlZGVudGlhbChjcmVkZW50aWFsKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBFaXRoZXIgdGhlIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIElEIHRva2VuLCBhY2Nlc3MgdG9rZW4gYW5kIHJhdyBub25jZVxuICAgKiBvciB0aGUgSUQgdG9rZW4gc3RyaW5nLlxuICAgKi9cbiAgY3JlZGVudGlhbChwYXJhbXM6IE9BdXRoQ3JlZGVudGlhbE9wdGlvbnMpOiBPQXV0aENyZWRlbnRpYWwge1xuICAgIHJldHVybiB0aGlzLl9jcmVkZW50aWFsKHsgLi4ucGFyYW1zLCBub25jZTogcGFyYW1zLnJhd05vbmNlIH0pO1xuICB9XG5cbiAgLyoqIEFuIGludGVybmFsIGNyZWRlbnRpYWwgbWV0aG9kIHRoYXQgYWNjZXB0cyBtb3JlIHBlcm1pc3NpdmUgb3B0aW9ucyAqL1xuICBwcml2YXRlIF9jcmVkZW50aWFsKFxuICAgIHBhcmFtczogT21pdDxPQXV0aENyZWRlbnRpYWxQYXJhbXMsICdzaWduSW5NZXRob2QnIHwgJ3Byb3ZpZGVySWQnPlxuICApOiBPQXV0aENyZWRlbnRpYWwge1xuICAgIF9hc3NlcnQocGFyYW1zLmlkVG9rZW4gfHwgcGFyYW1zLmFjY2Vzc1Rva2VuLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICAvLyBGb3IgT0F1dGhDcmVkZW50aWFsLCBzaWduIGluIG1ldGhvZCBpcyBzYW1lIGFzIHByb3ZpZGVySWQuXG4gICAgcmV0dXJuIE9BdXRoQ3JlZGVudGlhbC5fZnJvbVBhcmFtcyh7XG4gICAgICAuLi5wYXJhbXMsXG4gICAgICBwcm92aWRlcklkOiB0aGlzLnByb3ZpZGVySWQsXG4gICAgICBzaWduSW5NZXRob2Q6IHRoaXMucHJvdmlkZXJJZFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXh0cmFjdCB0aGUgdW5kZXJseWluZyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmcm9tIGEge0BsaW5rIFVzZXJDcmVkZW50aWFsfS5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbVJlc3VsdChcbiAgICB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWxcbiAgKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIE9BdXRoUHJvdmlkZXIub2F1dGhDcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIHVzZXJDcmVkZW50aWFsIGFzIFVzZXJDcmVkZW50aWFsSW50ZXJuYWxcbiAgICApO1xuICB9XG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBBdXRoRXJyb3J9IHdoaWNoIHdhc1xuICAgKiB0aHJvd24gZHVyaW5nIGEgc2lnbi1pbiwgbGluaywgb3IgcmVhdXRoZW50aWNhdGUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tRXJyb3IoZXJyb3I6IEZpcmViYXNlRXJyb3IpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gT0F1dGhQcm92aWRlci5vYXV0aENyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIG9hdXRoQ3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3Qoe1xuICAgIF90b2tlblJlc3BvbnNlOiB0b2tlblJlc3BvbnNlXG4gIH06IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgaWYgKCF0b2tlblJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICBvYXV0aElkVG9rZW4sXG4gICAgICBvYXV0aEFjY2Vzc1Rva2VuLFxuICAgICAgb2F1dGhUb2tlblNlY3JldCxcbiAgICAgIHBlbmRpbmdUb2tlbixcbiAgICAgIG5vbmNlLFxuICAgICAgcHJvdmlkZXJJZFxuICAgIH0gPSB0b2tlblJlc3BvbnNlIGFzIFNpZ25JbldpdGhJZHBSZXNwb25zZTtcbiAgICBpZiAoXG4gICAgICAhb2F1dGhBY2Nlc3NUb2tlbiAmJlxuICAgICAgIW9hdXRoVG9rZW5TZWNyZXQgJiZcbiAgICAgICFvYXV0aElkVG9rZW4gJiZcbiAgICAgICFwZW5kaW5nVG9rZW5cbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmICghcHJvdmlkZXJJZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBuZXcgT0F1dGhQcm92aWRlcihwcm92aWRlcklkKS5fY3JlZGVudGlhbCh7XG4gICAgICAgIGlkVG9rZW46IG9hdXRoSWRUb2tlbixcbiAgICAgICAgYWNjZXNzVG9rZW46IG9hdXRoQWNjZXNzVG9rZW4sXG4gICAgICAgIG5vbmNlLFxuICAgICAgICBwZW5kaW5nVG9rZW5cbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEZpcmViYXNlRXJyb3IgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgT0F1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvb2F1dGgnO1xuaW1wb3J0IHsgQmFzZU9BdXRoUHJvdmlkZXIgfSBmcm9tICcuL29hdXRoJztcbmltcG9ydCB7IFByb3ZpZGVySWQsIFNpZ25Jbk1ldGhvZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuLyoqXG4gKiBQcm92aWRlciBmb3IgZ2VuZXJhdGluZyBhbiB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmb3Ige0BsaW5rIFByb3ZpZGVySWR9LkZBQ0VCT09LLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcmVkaXJlY3QuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBGYWNlYm9va0F1dGhQcm92aWRlcigpO1xuICogLy8gU3RhcnQgYSBzaWduIGluIHByb2Nlc3MgZm9yIGFuIHVuYXV0aGVudGljYXRlZCB1c2VyLlxuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3VzZXJfYmlydGhkYXknKTtcbiAqIGF3YWl0IHNpZ25JbldpdGhSZWRpcmVjdChhdXRoLCBwcm92aWRlcik7XG4gKiAvLyBUaGlzIHdpbGwgdHJpZ2dlciBhIGZ1bGwgcGFnZSByZWRpcmVjdCBhd2F5IGZyb20geW91ciBhcHBcbiAqXG4gKiAvLyBBZnRlciByZXR1cm5pbmcgZnJvbSB0aGUgcmVkaXJlY3Qgd2hlbiB5b3VyIGFwcCBpbml0aWFsaXplcyB5b3UgY2FuIG9idGFpbiB0aGUgcmVzdWx0XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRSZWRpcmVjdFJlc3VsdChhdXRoKTtcbiAqIGlmIChyZXN1bHQpIHtcbiAqICAgLy8gVGhpcyBpcyB0aGUgc2lnbmVkLWluIHVzZXJcbiAqICAgY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogICAvLyBUaGlzIGdpdmVzIHlvdSBhIEZhY2Vib29rIEFjY2VzcyBUb2tlbi5cbiAqICAgY29uc3QgY3JlZGVudGlhbCA9IEZhY2Vib29rQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiAgIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcG9wdXAuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBGYWNlYm9va0F1dGhQcm92aWRlcigpO1xuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3VzZXJfYmlydGhkYXknKTtcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNpZ25JbldpdGhQb3B1cChhdXRoLCBwcm92aWRlcik7XG4gKlxuICogLy8gVGhlIHNpZ25lZC1pbiB1c2VyIGluZm8uXG4gKiBjb25zdCB1c2VyID0gcmVzdWx0LnVzZXI7XG4gKiAvLyBUaGlzIGdpdmVzIHlvdSBhIEZhY2Vib29rIEFjY2VzcyBUb2tlbi5cbiAqIGNvbnN0IGNyZWRlbnRpYWwgPSBGYWNlYm9va0F1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogY29uc3QgdG9rZW4gPSBjcmVkZW50aWFsLmFjY2Vzc1Rva2VuO1xuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgRmFjZWJvb2tBdXRoUHJvdmlkZXIgZXh0ZW5kcyBCYXNlT0F1dGhQcm92aWRlciB7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkZBQ0VCT09LLiAqL1xuICBzdGF0aWMgcmVhZG9ubHkgRkFDRUJPT0tfU0lHTl9JTl9NRVRIT0Q6ICdmYWNlYm9vay5jb20nID1cbiAgICBTaWduSW5NZXRob2QuRkFDRUJPT0s7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5GQUNFQk9PSy4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IFBST1ZJREVSX0lEOiAnZmFjZWJvb2suY29tJyA9IFByb3ZpZGVySWQuRkFDRUJPT0s7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoUHJvdmlkZXJJZC5GQUNFQk9PSyk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGNyZWRlbnRpYWwgZm9yIEZhY2Vib29rLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqYXZhc2NyaXB0XG4gICAqIC8vIGBldmVudGAgZnJvbSB0aGUgRmFjZWJvb2sgYXV0aC5hdXRoUmVzcG9uc2VDaGFuZ2UgY2FsbGJhY2suXG4gICAqIGNvbnN0IGNyZWRlbnRpYWwgPSBGYWNlYm9va0F1dGhQcm92aWRlci5jcmVkZW50aWFsKGV2ZW50LmF1dGhSZXNwb25zZS5hY2Nlc3NUb2tlbik7XG4gICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNpZ25JbldpdGhDcmVkZW50aWFsKGNyZWRlbnRpYWwpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIGFjY2Vzc1Rva2VuIC0gRmFjZWJvb2sgYWNjZXNzIHRva2VuLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWwoYWNjZXNzVG9rZW46IHN0cmluZyk6IE9BdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIE9BdXRoQ3JlZGVudGlhbC5fZnJvbVBhcmFtcyh7XG4gICAgICBwcm92aWRlcklkOiBGYWNlYm9va0F1dGhQcm92aWRlci5QUk9WSURFUl9JRCxcbiAgICAgIHNpZ25Jbk1ldGhvZDogRmFjZWJvb2tBdXRoUHJvdmlkZXIuRkFDRUJPT0tfU0lHTl9JTl9NRVRIT0QsXG4gICAgICBhY2Nlc3NUb2tlblxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXh0cmFjdCB0aGUgdW5kZXJseWluZyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmcm9tIGEge0BsaW5rIFVzZXJDcmVkZW50aWFsfS5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbVJlc3VsdChcbiAgICB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWxcbiAgKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIEZhY2Vib29rQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgdXNlckNyZWRlbnRpYWwgYXMgVXNlckNyZWRlbnRpYWxJbnRlcm5hbFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSB7QGxpbmsgQXV0aEVycm9yfSB3aGljaCB3YXNcbiAgICogdGhyb3duIGR1cmluZyBhIHNpZ24taW4sIGxpbmssIG9yIHJlYXV0aGVudGljYXRlIG9wZXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbUVycm9yKGVycm9yOiBGaXJlYmFzZUVycm9yKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIEZhY2Vib29rQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KHtcbiAgICBfdG9rZW5SZXNwb25zZTogdG9rZW5SZXNwb25zZVxuICB9OiBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGlmICghdG9rZW5SZXNwb25zZSB8fCAhKCdvYXV0aEFjY2Vzc1Rva2VuJyBpbiB0b2tlblJlc3BvbnNlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlblJlc3BvbnNlLm9hdXRoQWNjZXNzVG9rZW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gRmFjZWJvb2tBdXRoUHJvdmlkZXIuY3JlZGVudGlhbCh0b2tlblJlc3BvbnNlLm9hdXRoQWNjZXNzVG9rZW4pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgU2lnbkluV2l0aElkcFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2lkcCc7XG5pbXBvcnQgeyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IE9BdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4uL2NyZWRlbnRpYWxzL29hdXRoJztcbmltcG9ydCB7IEJhc2VPQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi9vYXV0aCc7XG5pbXBvcnQgeyBQcm92aWRlcklkLCBTaWduSW5NZXRob2QgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5cbi8qKlxuICogUHJvdmlkZXIgZm9yIGdlbmVyYXRpbmcgYW4ge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZm9yIHtAbGluayBQcm92aWRlcklkfS5HT09HTEUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIC8vIFNpZ24gaW4gdXNpbmcgYSByZWRpcmVjdC5cbiAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IEdvb2dsZUF1dGhQcm92aWRlcigpO1xuICogLy8gU3RhcnQgYSBzaWduIGluIHByb2Nlc3MgZm9yIGFuIHVuYXV0aGVudGljYXRlZCB1c2VyLlxuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdlbWFpbCcpO1xuICogYXdhaXQgc2lnbkluV2l0aFJlZGlyZWN0KGF1dGgsIHByb3ZpZGVyKTtcbiAqIC8vIFRoaXMgd2lsbCB0cmlnZ2VyIGEgZnVsbCBwYWdlIHJlZGlyZWN0IGF3YXkgZnJvbSB5b3VyIGFwcFxuICpcbiAqIC8vIEFmdGVyIHJldHVybmluZyBmcm9tIHRoZSByZWRpcmVjdCB3aGVuIHlvdXIgYXBwIGluaXRpYWxpemVzIHlvdSBjYW4gb2J0YWluIHRoZSByZXN1bHRcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldFJlZGlyZWN0UmVzdWx0KGF1dGgpO1xuICogaWYgKHJlc3VsdCkge1xuICogICAvLyBUaGlzIGlzIHRoZSBzaWduZWQtaW4gdXNlclxuICogICBjb25zdCB1c2VyID0gcmVzdWx0LnVzZXI7XG4gKiAgIC8vIFRoaXMgZ2l2ZXMgeW91IGEgR29vZ2xlIEFjY2VzcyBUb2tlbi5cbiAqICAgY29uc3QgY3JlZGVudGlhbCA9IEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogICBjb25zdCB0b2tlbiA9IGNyZWRlbnRpYWwuYWNjZXNzVG9rZW47XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHBvcHVwLlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgR29vZ2xlQXV0aFByb3ZpZGVyKCk7XG4gKiBwcm92aWRlci5hZGRTY29wZSgncHJvZmlsZScpO1xuICogcHJvdmlkZXIuYWRkU2NvcGUoJ2VtYWlsJyk7XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoUG9wdXAoYXV0aCwgcHJvdmlkZXIpO1xuICpcbiAqIC8vIFRoZSBzaWduZWQtaW4gdXNlciBpbmZvLlxuICogY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogLy8gVGhpcyBnaXZlcyB5b3UgYSBHb29nbGUgQWNjZXNzIFRva2VuLlxuICogY29uc3QgY3JlZGVudGlhbCA9IEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogY29uc3QgdG9rZW4gPSBjcmVkZW50aWFsLmFjY2Vzc1Rva2VuO1xuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgR29vZ2xlQXV0aFByb3ZpZGVyIGV4dGVuZHMgQmFzZU9BdXRoUHJvdmlkZXIge1xuICAvKiogQWx3YXlzIHNldCB0byB7QGxpbmsgU2lnbkluTWV0aG9kfS5HT09HTEUuICovXG4gIHN0YXRpYyByZWFkb25seSBHT09HTEVfU0lHTl9JTl9NRVRIT0Q6ICdnb29nbGUuY29tJyA9IFNpZ25Jbk1ldGhvZC5HT09HTEU7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5HT09HTEUuICovXG4gIHN0YXRpYyByZWFkb25seSBQUk9WSURFUl9JRDogJ2dvb2dsZS5jb20nID0gUHJvdmlkZXJJZC5HT09HTEU7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoUHJvdmlkZXJJZC5HT09HTEUpO1xuICAgIHRoaXMuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY3JlZGVudGlhbCBmb3IgR29vZ2xlLiBBdCBsZWFzdCBvbmUgb2YgSUQgdG9rZW4gYW5kIGFjY2VzcyB0b2tlbiBpcyByZXF1aXJlZC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgamF2YXNjcmlwdFxuICAgKiAvLyBcXGBnb29nbGVVc2VyXFxgIGZyb20gdGhlIG9uc3VjY2VzcyBHb29nbGUgU2lnbiBJbiBjYWxsYmFjay5cbiAgICogY29uc3QgY3JlZGVudGlhbCA9IEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsKGdvb2dsZVVzZXIuZ2V0QXV0aFJlc3BvbnNlKCkuaWRfdG9rZW4pO1xuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoQ3JlZGVudGlhbChjcmVkZW50aWFsKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBpZFRva2VuIC0gR29vZ2xlIElEIHRva2VuLlxuICAgKiBAcGFyYW0gYWNjZXNzVG9rZW4gLSBHb29nbGUgYWNjZXNzIHRva2VuLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWwoXG4gICAgaWRUb2tlbj86IHN0cmluZyB8IG51bGwsXG4gICAgYWNjZXNzVG9rZW4/OiBzdHJpbmcgfCBudWxsXG4gICk6IE9BdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIE9BdXRoQ3JlZGVudGlhbC5fZnJvbVBhcmFtcyh7XG4gICAgICBwcm92aWRlcklkOiBHb29nbGVBdXRoUHJvdmlkZXIuUFJPVklERVJfSUQsXG4gICAgICBzaWduSW5NZXRob2Q6IEdvb2dsZUF1dGhQcm92aWRlci5HT09HTEVfU0lHTl9JTl9NRVRIT0QsXG4gICAgICBpZFRva2VuLFxuICAgICAgYWNjZXNzVG9rZW5cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBVc2VyQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyQ3JlZGVudGlhbCAtIFRoZSB1c2VyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21SZXN1bHQoXG4gICAgdXNlckNyZWRlbnRpYWw6IFVzZXJDcmVkZW50aWFsXG4gICk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBHb29nbGVBdXRoUHJvdmlkZXIuY3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3QoXG4gICAgICB1c2VyQ3JlZGVudGlhbCBhcyBVc2VyQ3JlZGVudGlhbEludGVybmFsXG4gICAgKTtcbiAgfVxuICAvKipcbiAgICogVXNlZCB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSB7QGxpbmsgQXV0aEVycm9yfSB3aGljaCB3YXNcbiAgICogdGhyb3duIGR1cmluZyBhIHNpZ24taW4sIGxpbmssIG9yIHJlYXV0aGVudGljYXRlIG9wZXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbUVycm9yKGVycm9yOiBGaXJlYmFzZUVycm9yKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIChlcnJvci5jdXN0b21EYXRhIHx8IHt9KSBhcyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBjcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdCh7XG4gICAgX3Rva2VuUmVzcG9uc2U6IHRva2VuUmVzcG9uc2VcbiAgfTogVGFnZ2VkV2l0aFRva2VuUmVzcG9uc2UpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICBpZiAoIXRva2VuUmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHsgb2F1dGhJZFRva2VuLCBvYXV0aEFjY2Vzc1Rva2VuIH0gPVxuICAgICAgdG9rZW5SZXNwb25zZSBhcyBTaWduSW5XaXRoSWRwUmVzcG9uc2U7XG4gICAgaWYgKCFvYXV0aElkVG9rZW4gJiYgIW9hdXRoQWNjZXNzVG9rZW4pIHtcbiAgICAgIC8vIFRoaXMgY291bGQgYmUgYW4gb2F1dGggMSBjcmVkZW50aWFsIG9yIGEgcGhvbmUgY3JlZGVudGlhbFxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBHb29nbGVBdXRoUHJvdmlkZXIuY3JlZGVudGlhbChvYXV0aElkVG9rZW4sIG9hdXRoQWNjZXNzVG9rZW4pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgVGFnZ2VkV2l0aFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBPQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuLi9jcmVkZW50aWFscy9vYXV0aCc7XG5pbXBvcnQgeyBCYXNlT0F1dGhQcm92aWRlciB9IGZyb20gJy4vb2F1dGgnO1xuaW1wb3J0IHsgUHJvdmlkZXJJZCwgU2lnbkluTWV0aG9kIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBnZW5lcmF0aW5nIGFuIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZvciB7QGxpbmsgUHJvdmlkZXJJZH0uR0lUSFVCLlxuICpcbiAqIEByZW1hcmtzXG4gKiBHaXRIdWIgcmVxdWlyZXMgYW4gT0F1dGggMi4wIHJlZGlyZWN0LCBzbyB5b3UgY2FuIGVpdGhlciBoYW5kbGUgdGhlIHJlZGlyZWN0IGRpcmVjdGx5LCBvciB1c2VcbiAqIHRoZSB7QGxpbmsgc2lnbkluV2l0aFBvcHVwfSBoYW5kbGVyOlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcmVkaXJlY3QuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBHaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAqIC8vIFN0YXJ0IGEgc2lnbiBpbiBwcm9jZXNzIGZvciBhbiB1bmF1dGhlbnRpY2F0ZWQgdXNlci5cbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdyZXBvJyk7XG4gKiBhd2FpdCBzaWduSW5XaXRoUmVkaXJlY3QoYXV0aCwgcHJvdmlkZXIpO1xuICogLy8gVGhpcyB3aWxsIHRyaWdnZXIgYSBmdWxsIHBhZ2UgcmVkaXJlY3QgYXdheSBmcm9tIHlvdXIgYXBwXG4gKlxuICogLy8gQWZ0ZXIgcmV0dXJuaW5nIGZyb20gdGhlIHJlZGlyZWN0IHdoZW4geW91ciBhcHAgaW5pdGlhbGl6ZXMgeW91IGNhbiBvYnRhaW4gdGhlIHJlc3VsdFxuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2V0UmVkaXJlY3RSZXN1bHQoYXV0aCk7XG4gKiBpZiAocmVzdWx0KSB7XG4gKiAgIC8vIFRoaXMgaXMgdGhlIHNpZ25lZC1pbiB1c2VyXG4gKiAgIGNvbnN0IHVzZXIgPSByZXN1bHQudXNlcjtcbiAqICAgLy8gVGhpcyBnaXZlcyB5b3UgYSBHaXRIdWIgQWNjZXNzIFRva2VuLlxuICogICBjb25zdCBjcmVkZW50aWFsID0gR2l0aHViQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiAgIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcG9wdXAuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBHaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdyZXBvJyk7XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoUG9wdXAoYXV0aCwgcHJvdmlkZXIpO1xuICpcbiAqIC8vIFRoZSBzaWduZWQtaW4gdXNlciBpbmZvLlxuICogY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogLy8gVGhpcyBnaXZlcyB5b3UgYSBHaXRIdWIgQWNjZXNzIFRva2VuLlxuICogY29uc3QgY3JlZGVudGlhbCA9IEdpdGh1YkF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogY29uc3QgdG9rZW4gPSBjcmVkZW50aWFsLmFjY2Vzc1Rva2VuO1xuICogYGBgXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBHaXRodWJBdXRoUHJvdmlkZXIgZXh0ZW5kcyBCYXNlT0F1dGhQcm92aWRlciB7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkdJVEhVQi4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IEdJVEhVQl9TSUdOX0lOX01FVEhPRDogJ2dpdGh1Yi5jb20nID0gU2lnbkluTWV0aG9kLkdJVEhVQjtcbiAgLyoqIEFsd2F5cyBzZXQgdG8ge0BsaW5rIFByb3ZpZGVySWR9LkdJVEhVQi4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IFBST1ZJREVSX0lEOiAnZ2l0aHViLmNvbScgPSBQcm92aWRlcklkLkdJVEhVQjtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihQcm92aWRlcklkLkdJVEhVQik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGNyZWRlbnRpYWwgZm9yIEdpdEh1Yi5cbiAgICpcbiAgICogQHBhcmFtIGFjY2Vzc1Rva2VuIC0gR2l0SHViIGFjY2VzcyB0b2tlbi5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsKGFjY2Vzc1Rva2VuOiBzdHJpbmcpOiBPQXV0aENyZWRlbnRpYWwge1xuICAgIHJldHVybiBPQXV0aENyZWRlbnRpYWwuX2Zyb21QYXJhbXMoe1xuICAgICAgcHJvdmlkZXJJZDogR2l0aHViQXV0aFByb3ZpZGVyLlBST1ZJREVSX0lELFxuICAgICAgc2lnbkluTWV0aG9kOiBHaXRodWJBdXRoUHJvdmlkZXIuR0lUSFVCX1NJR05fSU5fTUVUSE9ELFxuICAgICAgYWNjZXNzVG9rZW5cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBVc2VyQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyQ3JlZGVudGlhbCAtIFRoZSB1c2VyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21SZXN1bHQoXG4gICAgdXNlckNyZWRlbnRpYWw6IFVzZXJDcmVkZW50aWFsXG4gICk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBHaXRodWJBdXRoUHJvdmlkZXIuY3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3QoXG4gICAgICB1c2VyQ3JlZGVudGlhbCBhcyBVc2VyQ3JlZGVudGlhbEludGVybmFsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBBdXRoRXJyb3J9IHdoaWNoIHdhc1xuICAgKiB0aHJvd24gZHVyaW5nIGEgc2lnbi1pbiwgbGluaywgb3IgcmVhdXRoZW50aWNhdGUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tRXJyb3IoZXJyb3I6IEZpcmViYXNlRXJyb3IpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gR2l0aHViQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KHtcbiAgICBfdG9rZW5SZXNwb25zZTogdG9rZW5SZXNwb25zZVxuICB9OiBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGlmICghdG9rZW5SZXNwb25zZSB8fCAhKCdvYXV0aEFjY2Vzc1Rva2VuJyBpbiB0b2tlblJlc3BvbnNlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlblJlc3BvbnNlLm9hdXRoQWNjZXNzVG9rZW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gR2l0aHViQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWwodG9rZW5SZXNwb25zZS5vYXV0aEFjY2Vzc1Rva2VuKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgU0FNTCBjcmVkZW50aWFscyByZXR1cm5lZCBieSBhbiB7QGxpbmsgU0FNTEF1dGhQcm92aWRlcn0uXG4gKlxuICogQHB1YmxpY1xuICovXG5cbmltcG9ydCB7XG4gIHNpZ25JbldpdGhJZHAsXG4gIFNpZ25JbldpdGhJZHBSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9pZHAnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vYXV0aF9jcmVkZW50aWFsJztcblxuY29uc3QgSURQX1JFUVVFU1RfVVJJID0gJ2h0dHA6Ly9sb2NhbGhvc3QnO1xuXG4vKipcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFNBTUxBdXRoQ3JlZGVudGlhbCBleHRlbmRzIEF1dGhDcmVkZW50aWFsIHtcbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHByb3ZpZGVySWQ6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdUb2tlbjogc3RyaW5nXG4gICkge1xuICAgIHN1cGVyKHByb3ZpZGVySWQsIHByb3ZpZGVySWQpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuYnVpbGRSZXF1ZXN0KCk7XG4gICAgcmV0dXJuIHNpZ25JbldpdGhJZHAoYXV0aCwgcmVxdWVzdCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9saW5rVG9JZFRva2VuKFxuICAgIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBpZFRva2VuOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QoKTtcbiAgICByZXF1ZXN0LmlkVG9rZW4gPSBpZFRva2VuO1xuICAgIHJldHVybiBzaWduSW5XaXRoSWRwKGF1dGgsIHJlcXVlc3QpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0UmVhdXRoZW50aWNhdGlvblJlc29sdmVyKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuYnVpbGRSZXF1ZXN0KCk7XG4gICAgcmVxdWVzdC5hdXRvQ3JlYXRlID0gZmFsc2U7XG4gICAgcmV0dXJuIHNpZ25JbldpdGhJZHAoYXV0aCwgcmVxdWVzdCk7XG4gIH1cblxuICAvKioge0Bpbmhlcml0ZG9jIEF1dGhDcmVkZW50aWFsLnRvSlNPTn0gICovXG4gIHRvSlNPTigpOiBvYmplY3Qge1xuICAgIHJldHVybiB7XG4gICAgICBzaWduSW5NZXRob2Q6IHRoaXMuc2lnbkluTWV0aG9kLFxuICAgICAgcHJvdmlkZXJJZDogdGhpcy5wcm92aWRlcklkLFxuICAgICAgcGVuZGluZ1Rva2VuOiB0aGlzLnBlbmRpbmdUb2tlblxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU3RhdGljIG1ldGhvZCB0byBkZXNlcmlhbGl6ZSBhIEpTT04gcmVwcmVzZW50YXRpb24gb2YgYW4gb2JqZWN0IGludG8gYW5cbiAgICoge0BsaW5rICBBdXRoQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSBqc29uIC0gSW5wdXQgY2FuIGJlIGVpdGhlciBPYmplY3Qgb3IgdGhlIHN0cmluZ2lmaWVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBvYmplY3QuXG4gICAqIFdoZW4gc3RyaW5nIGlzIHByb3ZpZGVkLCBKU09OLnBhcnNlIHdvdWxkIGJlIGNhbGxlZCBmaXJzdC5cbiAgICpcbiAgICogQHJldHVybnMgSWYgdGhlIEpTT04gaW5wdXQgZG9lcyBub3QgcmVwcmVzZW50IGFuIHtAbGluayAgQXV0aENyZWRlbnRpYWx9LCBudWxsIGlzIHJldHVybmVkLlxuICAgKi9cbiAgc3RhdGljIGZyb21KU09OKGpzb246IHN0cmluZyB8IG9iamVjdCk6IFNBTUxBdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGNvbnN0IG9iaiA9IHR5cGVvZiBqc29uID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UoanNvbikgOiBqc29uO1xuICAgIGNvbnN0IHsgcHJvdmlkZXJJZCwgc2lnbkluTWV0aG9kLCBwZW5kaW5nVG9rZW4gfTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9XG4gICAgICBvYmo7XG4gICAgaWYgKFxuICAgICAgIXByb3ZpZGVySWQgfHxcbiAgICAgICFzaWduSW5NZXRob2QgfHxcbiAgICAgICFwZW5kaW5nVG9rZW4gfHxcbiAgICAgIHByb3ZpZGVySWQgIT09IHNpZ25Jbk1ldGhvZFxuICAgICkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBTQU1MQXV0aENyZWRlbnRpYWwocHJvdmlkZXJJZCwgcGVuZGluZ1Rva2VuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgc3RhdGljIG1ldGhvZCB0byBhdm9pZCBleHBvc2luZyB0aGUgY29uc3RydWN0b3IgdG8gZW5kIHVzZXJzLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHN0YXRpYyBfY3JlYXRlKHByb3ZpZGVySWQ6IHN0cmluZywgcGVuZGluZ1Rva2VuOiBzdHJpbmcpOiBTQU1MQXV0aENyZWRlbnRpYWwge1xuICAgIHJldHVybiBuZXcgU0FNTEF1dGhDcmVkZW50aWFsKHByb3ZpZGVySWQsIHBlbmRpbmdUb2tlbik7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkUmVxdWVzdCgpOiBTaWduSW5XaXRoSWRwUmVxdWVzdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlcXVlc3RVcmk6IElEUF9SRVFVRVNUX1VSSSxcbiAgICAgIHJldHVyblNlY3VyZVRva2VuOiB0cnVlLFxuICAgICAgcGVuZGluZ1Rva2VuOiB0aGlzLnBlbmRpbmdUb2tlblxuICAgIH07XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgU2lnbkluV2l0aElkcFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2lkcCc7XG5pbXBvcnQgeyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMnO1xuaW1wb3J0IHsgU0FNTEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvc2FtbCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBGZWRlcmF0ZWRBdXRoUHJvdmlkZXIgfSBmcm9tICcuL2ZlZGVyYXRlZCc7XG5cbmNvbnN0IFNBTUxfUFJPVklERVJfUFJFRklYID0gJ3NhbWwuJztcblxuLyoqXG4gKiBBbiB7QGxpbmsgQXV0aFByb3ZpZGVyfSBmb3IgU0FNTC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBTQU1MQXV0aFByb3ZpZGVyIGV4dGVuZHMgRmVkZXJhdGVkQXV0aFByb3ZpZGVyIHtcbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yLiBUaGUgcHJvdmlkZXJJZCBtdXN0IHN0YXJ0IHdpdGggXCJzYW1sLlwiXG4gICAqIEBwYXJhbSBwcm92aWRlcklkIC0gU0FNTCBwcm92aWRlciBJRC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb3ZpZGVySWQ6IHN0cmluZykge1xuICAgIF9hc3NlcnQoXG4gICAgICBwcm92aWRlcklkLnN0YXJ0c1dpdGgoU0FNTF9QUk9WSURFUl9QUkVGSVgpLFxuICAgICAgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUlxuICAgICk7XG4gICAgc3VwZXIocHJvdmlkZXJJZCk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuIHtAbGluayBBdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBVc2VyQ3JlZGVudGlhbH0gYWZ0ZXIgYVxuICAgKiBzdWNjZXNzZnVsIFNBTUwgZmxvdyBjb21wbGV0ZXMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB0byBnZXQgYW4ge0BsaW5rIEF1dGhDcmVkZW50aWFsfSwgeW91IGNvdWxkIHdyaXRlIHRoZVxuICAgKiBmb2xsb3dpbmcgY29kZTpcbiAgICpcbiAgICogYGBganNcbiAgICogY29uc3QgdXNlckNyZWRlbnRpYWwgPSBhd2FpdCBzaWduSW5XaXRoUG9wdXAoYXV0aCwgc2FtbFByb3ZpZGVyKTtcbiAgICogY29uc3QgY3JlZGVudGlhbCA9IFNBTUxBdXRoUHJvdmlkZXIuY3JlZGVudGlhbEZyb21SZXN1bHQodXNlckNyZWRlbnRpYWwpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbVJlc3VsdChcbiAgICB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWxcbiAgKTogQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gU0FNTEF1dGhQcm92aWRlci5zYW1sQ3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3QoXG4gICAgICB1c2VyQ3JlZGVudGlhbCBhcyBVc2VyQ3JlZGVudGlhbEludGVybmFsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBBdXRoRXJyb3J9IHdoaWNoIHdhc1xuICAgKiB0aHJvd24gZHVyaW5nIGEgc2lnbi1pbiwgbGluaywgb3IgcmVhdXRoZW50aWNhdGUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tRXJyb3IoZXJyb3I6IEZpcmViYXNlRXJyb3IpOiBBdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBTQU1MQXV0aFByb3ZpZGVyLnNhbWxDcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIChlcnJvci5jdXN0b21EYXRhIHx8IHt9KSBhcyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiB7QGxpbmsgQXV0aENyZWRlbnRpYWx9IGZyb20gYSBKU09OIHN0cmluZyBvciBhIHBsYWluIG9iamVjdC5cbiAgICogQHBhcmFtIGpzb24gLSBBIHBsYWluIG9iamVjdCBvciBhIEpTT04gc3RyaW5nXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21KU09OKGpzb246IHN0cmluZyB8IG9iamVjdCk6IEF1dGhDcmVkZW50aWFsIHtcbiAgICBjb25zdCBjcmVkZW50aWFsID0gU0FNTEF1dGhDcmVkZW50aWFsLmZyb21KU09OKGpzb24pO1xuICAgIF9hc3NlcnQoY3JlZGVudGlhbCwgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUik7XG4gICAgcmV0dXJuIGNyZWRlbnRpYWw7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBzYW1sQ3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3Qoe1xuICAgIF90b2tlblJlc3BvbnNlOiB0b2tlblJlc3BvbnNlXG4gIH06IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlKTogU0FNTEF1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgaWYgKCF0b2tlblJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB7IHBlbmRpbmdUb2tlbiwgcHJvdmlkZXJJZCB9ID0gdG9rZW5SZXNwb25zZSBhcyBTaWduSW5XaXRoSWRwUmVzcG9uc2U7XG5cbiAgICBpZiAoIXBlbmRpbmdUb2tlbiB8fCAhcHJvdmlkZXJJZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBTQU1MQXV0aENyZWRlbnRpYWwuX2NyZWF0ZShwcm92aWRlcklkLCBwZW5kaW5nVG9rZW4pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIFR3aXR0ZXIgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQgeyBTaWduSW5XaXRoSWRwUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vaWRwJztcbmltcG9ydCB7IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgT0F1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvb2F1dGgnO1xuaW1wb3J0IHsgQmFzZU9BdXRoUHJvdmlkZXIgfSBmcm9tICcuL29hdXRoJztcbmltcG9ydCB7IFByb3ZpZGVySWQsIFNpZ25Jbk1ldGhvZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuLyoqXG4gKiBQcm92aWRlciBmb3IgZ2VuZXJhdGluZyBhbiB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmb3Ige0BsaW5rIFByb3ZpZGVySWR9LlRXSVRURVIuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIC8vIFNpZ24gaW4gdXNpbmcgYSByZWRpcmVjdC5cbiAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IFR3aXR0ZXJBdXRoUHJvdmlkZXIoKTtcbiAqIC8vIFN0YXJ0IGEgc2lnbiBpbiBwcm9jZXNzIGZvciBhbiB1bmF1dGhlbnRpY2F0ZWQgdXNlci5cbiAqIGF3YWl0IHNpZ25JbldpdGhSZWRpcmVjdChhdXRoLCBwcm92aWRlcik7XG4gKiAvLyBUaGlzIHdpbGwgdHJpZ2dlciBhIGZ1bGwgcGFnZSByZWRpcmVjdCBhd2F5IGZyb20geW91ciBhcHBcbiAqXG4gKiAvLyBBZnRlciByZXR1cm5pbmcgZnJvbSB0aGUgcmVkaXJlY3Qgd2hlbiB5b3VyIGFwcCBpbml0aWFsaXplcyB5b3UgY2FuIG9idGFpbiB0aGUgcmVzdWx0XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRSZWRpcmVjdFJlc3VsdChhdXRoKTtcbiAqIGlmIChyZXN1bHQpIHtcbiAqICAgLy8gVGhpcyBpcyB0aGUgc2lnbmVkLWluIHVzZXJcbiAqICAgY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogICAvLyBUaGlzIGdpdmVzIHlvdSBhIFR3aXR0ZXIgQWNjZXNzIFRva2VuIGFuZCBTZWNyZXQuXG4gKiAgIGNvbnN0IGNyZWRlbnRpYWwgPSBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiAgIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqICAgY29uc3Qgc2VjcmV0ID0gY3JlZGVudGlhbC5zZWNyZXQ7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHBvcHVwLlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgVHdpdHRlckF1dGhQcm92aWRlcigpO1xuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgc2lnbkluV2l0aFBvcHVwKGF1dGgsIHByb3ZpZGVyKTtcbiAqXG4gKiAvLyBUaGUgc2lnbmVkLWluIHVzZXIgaW5mby5cbiAqIGNvbnN0IHVzZXIgPSByZXN1bHQudXNlcjtcbiAqIC8vIFRoaXMgZ2l2ZXMgeW91IGEgVHdpdHRlciBBY2Nlc3MgVG9rZW4gYW5kIFNlY3JldC5cbiAqIGNvbnN0IGNyZWRlbnRpYWwgPSBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiBjb25zdCB0b2tlbiA9IGNyZWRlbnRpYWwuYWNjZXNzVG9rZW47XG4gKiBjb25zdCBzZWNyZXQgPSBjcmVkZW50aWFsLnNlY3JldDtcbiAqIGBgYFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFR3aXR0ZXJBdXRoUHJvdmlkZXIgZXh0ZW5kcyBCYXNlT0F1dGhQcm92aWRlciB7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LlRXSVRURVIuICovXG4gIHN0YXRpYyByZWFkb25seSBUV0lUVEVSX1NJR05fSU5fTUVUSE9EOiAndHdpdHRlci5jb20nID0gU2lnbkluTWV0aG9kLlRXSVRURVI7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5UV0lUVEVSLiAqL1xuICBzdGF0aWMgcmVhZG9ubHkgUFJPVklERVJfSUQ6ICd0d2l0dGVyLmNvbScgPSBQcm92aWRlcklkLlRXSVRURVI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoUHJvdmlkZXJJZC5UV0lUVEVSKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY3JlZGVudGlhbCBmb3IgVHdpdHRlci5cbiAgICpcbiAgICogQHBhcmFtIHRva2VuIC0gVHdpdHRlciBhY2Nlc3MgdG9rZW4uXG4gICAqIEBwYXJhbSBzZWNyZXQgLSBUd2l0dGVyIHNlY3JldC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsKHRva2VuOiBzdHJpbmcsIHNlY3JldDogc3RyaW5nKTogT0F1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gT0F1dGhDcmVkZW50aWFsLl9mcm9tUGFyYW1zKHtcbiAgICAgIHByb3ZpZGVySWQ6IFR3aXR0ZXJBdXRoUHJvdmlkZXIuUFJPVklERVJfSUQsXG4gICAgICBzaWduSW5NZXRob2Q6IFR3aXR0ZXJBdXRoUHJvdmlkZXIuVFdJVFRFUl9TSUdOX0lOX01FVEhPRCxcbiAgICAgIG9hdXRoVG9rZW46IHRva2VuLFxuICAgICAgb2F1dGhUb2tlblNlY3JldDogc2VjcmV0XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSB7QGxpbmsgVXNlckNyZWRlbnRpYWx9LlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tUmVzdWx0KFxuICAgIHVzZXJDcmVkZW50aWFsOiBVc2VyQ3JlZGVudGlhbFxuICApOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gVHdpdHRlckF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIHVzZXJDcmVkZW50aWFsIGFzIFVzZXJDcmVkZW50aWFsSW50ZXJuYWxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXh0cmFjdCB0aGUgdW5kZXJseWluZyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmcm9tIGEge0BsaW5rIEF1dGhFcnJvcn0gd2hpY2ggd2FzXG4gICAqIHRocm93biBkdXJpbmcgYSBzaWduLWluLCBsaW5rLCBvciByZWF1dGhlbnRpY2F0ZSBvcGVyYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyQ3JlZGVudGlhbCAtIFRoZSB1c2VyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21FcnJvcihlcnJvcjogRmlyZWJhc2VFcnJvcik6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KHtcbiAgICBfdG9rZW5SZXNwb25zZTogdG9rZW5SZXNwb25zZVxuICB9OiBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGlmICghdG9rZW5SZXNwb25zZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHsgb2F1dGhBY2Nlc3NUb2tlbiwgb2F1dGhUb2tlblNlY3JldCB9ID1cbiAgICAgIHRva2VuUmVzcG9uc2UgYXMgU2lnbkluV2l0aElkcFJlc3BvbnNlO1xuICAgIGlmICghb2F1dGhBY2Nlc3NUb2tlbiB8fCAhb2F1dGhUb2tlblNlY3JldCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWwob2F1dGhBY2Nlc3NUb2tlbiwgb2F1dGhUb2tlblNlY3JldCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBFbmRwb2ludCxcbiAgSHR0cE1ldGhvZCxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhVmVyc2lvbixcbiAgX2FkZFRpZElmTmVjZXNzYXJ5LFxuICBfcGVyZm9ybVNpZ25JblJlcXVlc3Rcbn0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnblVwUmVxdWVzdCB7XG4gIGlkVG9rZW4/OiBzdHJpbmc7XG4gIHJldHVyblNlY3VyZVRva2VuPzogYm9vbGVhbjtcbiAgZW1haWw/OiBzdHJpbmc7XG4gIHBhc3N3b3JkPzogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgY2FwdGNoYVJlc3BvbnNlPzogc3RyaW5nO1xuICBjbGllbnRUeXBlPzogUmVjYXB0Y2hhQ2xpZW50VHlwZTtcbiAgcmVjYXB0Y2hhVmVyc2lvbj86IFJlY2FwdGNoYVZlcnNpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnblVwUmVzcG9uc2UgZXh0ZW5kcyBJZFRva2VuUmVzcG9uc2Uge1xuICBkaXNwbGF5TmFtZT86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduVXAoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25VcFJlcXVlc3Rcbik6IFByb21pc2U8U2lnblVwUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtU2lnbkluUmVxdWVzdDxTaWduVXBSZXF1ZXN0LCBTaWduVXBSZXNwb25zZT4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9VUCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBQaG9uZU9yT2F1dGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwsIFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IFVzZXJJbXBsIH0gZnJvbSAnLi91c2VyX2ltcGwnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlLCBQcm92aWRlcklkIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuXG5pbnRlcmZhY2UgVXNlckNyZWRlbnRpYWxQYXJhbXMge1xuICByZWFkb25seSB1c2VyOiBVc2VySW50ZXJuYWw7XG4gIHJlYWRvbmx5IHByb3ZpZGVySWQ6IFByb3ZpZGVySWQgfCBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBfdG9rZW5SZXNwb25zZT86IFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2U7XG4gIHJlYWRvbmx5IG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGU7XG59XG5cbmV4cG9ydCBjbGFzcyBVc2VyQ3JlZGVudGlhbEltcGxcbiAgaW1wbGVtZW50cyBVc2VyQ3JlZGVudGlhbEludGVybmFsLCBVc2VyQ3JlZGVudGlhbFBhcmFtc1xue1xuICByZWFkb25seSB1c2VyOiBVc2VySW50ZXJuYWw7XG4gIHJlYWRvbmx5IHByb3ZpZGVySWQ6IFByb3ZpZGVySWQgfCBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBfdG9rZW5SZXNwb25zZTogUGhvbmVPck9hdXRoVG9rZW5SZXNwb25zZSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgb3BlcmF0aW9uVHlwZTogT3BlcmF0aW9uVHlwZTtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IFVzZXJDcmVkZW50aWFsUGFyYW1zKSB7XG4gICAgdGhpcy51c2VyID0gcGFyYW1zLnVzZXI7XG4gICAgdGhpcy5wcm92aWRlcklkID0gcGFyYW1zLnByb3ZpZGVySWQ7XG4gICAgdGhpcy5fdG9rZW5SZXNwb25zZSA9IHBhcmFtcy5fdG9rZW5SZXNwb25zZTtcbiAgICB0aGlzLm9wZXJhdGlvblR5cGUgPSBwYXJhbXMub3BlcmF0aW9uVHlwZTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBfZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgb3BlcmF0aW9uVHlwZTogT3BlcmF0aW9uVHlwZSxcbiAgICBpZFRva2VuUmVzcG9uc2U6IElkVG9rZW5SZXNwb25zZSxcbiAgICBpc0Fub255bW91czogYm9vbGVhbiA9IGZhbHNlXG4gICk6IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbnRlcm5hbD4ge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCBVc2VySW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICAgIGF1dGgsXG4gICAgICBpZFRva2VuUmVzcG9uc2UsXG4gICAgICBpc0Fub255bW91c1xuICAgICk7XG4gICAgY29uc3QgcHJvdmlkZXJJZCA9IHByb3ZpZGVySWRGb3JSZXNwb25zZShpZFRva2VuUmVzcG9uc2UpO1xuICAgIGNvbnN0IHVzZXJDcmVkID0gbmV3IFVzZXJDcmVkZW50aWFsSW1wbCh7XG4gICAgICB1c2VyLFxuICAgICAgcHJvdmlkZXJJZCxcbiAgICAgIF90b2tlblJlc3BvbnNlOiBpZFRva2VuUmVzcG9uc2UsXG4gICAgICBvcGVyYXRpb25UeXBlXG4gICAgfSk7XG4gICAgcmV0dXJuIHVzZXJDcmVkO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIF9mb3JPcGVyYXRpb24oXG4gICAgdXNlcjogVXNlckludGVybmFsLFxuICAgIG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGUsXG4gICAgcmVzcG9uc2U6IFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2VcbiAgKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbEltcGw+IHtcbiAgICBhd2FpdCB1c2VyLl91cGRhdGVUb2tlbnNJZk5lY2Vzc2FyeShyZXNwb25zZSwgLyogcmVsb2FkICovIHRydWUpO1xuICAgIGNvbnN0IHByb3ZpZGVySWQgPSBwcm92aWRlcklkRm9yUmVzcG9uc2UocmVzcG9uc2UpO1xuICAgIHJldHVybiBuZXcgVXNlckNyZWRlbnRpYWxJbXBsKHtcbiAgICAgIHVzZXIsXG4gICAgICBwcm92aWRlcklkLFxuICAgICAgX3Rva2VuUmVzcG9uc2U6IHJlc3BvbnNlLFxuICAgICAgb3BlcmF0aW9uVHlwZVxuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIHByb3ZpZGVySWRGb3JSZXNwb25zZShcbiAgcmVzcG9uc2U6IElkVG9rZW5SZXNwb25zZVxuKTogUHJvdmlkZXJJZCB8IHN0cmluZyB8IG51bGwge1xuICBpZiAocmVzcG9uc2UucHJvdmlkZXJJZCkge1xuICAgIHJldHVybiByZXNwb25zZS5wcm92aWRlcklkO1xuICB9XG5cbiAgaWYgKCdwaG9uZU51bWJlcicgaW4gcmVzcG9uc2UpIHtcbiAgICByZXR1cm4gUHJvdmlkZXJJZC5QSE9ORTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEF1dGgsIFVzZXJDcmVkZW50aWFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IHNpZ25VcCB9IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9zaWduX3VwJztcbmltcG9ydCB7IFVzZXJJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbXBsIH0gZnJvbSAnLi4vdXNlci91c2VyX2NyZWRlbnRpYWxfaW1wbCc7XG5pbXBvcnQgeyBfY2FzdEF1dGggfSBmcm9tICcuLi9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgX2lzRmlyZWJhc2VTZXJ2ZXJBcHAgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yIH0gZnJvbSAnLi4vLi4vY29yZS91dGlsL2Fzc2VydCc7XG5cbi8qKlxuICogQXN5bmNocm9ub3VzbHkgc2lnbnMgaW4gYXMgYW4gYW5vbnltb3VzIHVzZXIuXG4gKlxuICogQHJlbWFya3NcbiAqIElmIHRoZXJlIGlzIGFscmVhZHkgYW4gYW5vbnltb3VzIHVzZXIgc2lnbmVkIGluLCB0aGF0IHVzZXIgd2lsbCBiZSByZXR1cm5lZDsgb3RoZXJ3aXNlLCBhXG4gKiBuZXcgYW5vbnltb3VzIHVzZXIgaWRlbnRpdHkgd2lsbCBiZSBjcmVhdGVkIGFuZCByZXR1cm5lZC5cbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluQW5vbnltb3VzbHkoYXV0aDogQXV0aCk6IFByb21pc2U8VXNlckNyZWRlbnRpYWw+IHtcbiAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKGF1dGgpXG4gICAgKTtcbiAgfVxuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG4gIGF3YWl0IGF1dGhJbnRlcm5hbC5faW5pdGlhbGl6YXRpb25Qcm9taXNlO1xuICBpZiAoYXV0aEludGVybmFsLmN1cnJlbnRVc2VyPy5pc0Fub255bW91cykge1xuICAgIC8vIElmIGFuIGFub255bW91cyB1c2VyIGlzIGFscmVhZHkgc2lnbmVkIGluLCBubyBuZWVkIHRvIHNpZ24gdGhlbSBpbiBhZ2Fpbi5cbiAgICByZXR1cm4gbmV3IFVzZXJDcmVkZW50aWFsSW1wbCh7XG4gICAgICB1c2VyOiBhdXRoSW50ZXJuYWwuY3VycmVudFVzZXIgYXMgVXNlckludGVybmFsLFxuICAgICAgcHJvdmlkZXJJZDogbnVsbCxcbiAgICAgIG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGUuU0lHTl9JTlxuICAgIH0pO1xuICB9XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgc2lnblVwKGF1dGhJbnRlcm5hbCwge1xuICAgIHJldHVyblNlY3VyZVRva2VuOiB0cnVlXG4gIH0pO1xuICBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IFVzZXJDcmVkZW50aWFsSW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgT3BlcmF0aW9uVHlwZS5TSUdOX0lOLFxuICAgIHJlc3BvbnNlLFxuICAgIHRydWVcbiAgKTtcbiAgYXdhaXQgYXV0aEludGVybmFsLl91cGRhdGVDdXJyZW50VXNlcih1c2VyQ3JlZGVudGlhbC51c2VyKTtcbiAgcmV0dXJuIHVzZXJDcmVkZW50aWFsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IE11bHRpRmFjdG9yRXJyb3IgYXMgTXVsdGlGYWN0b3JFcnJvclB1YmxpYyB9IGZyb20gJy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4uL2NvcmUvY3JlZGVudGlhbHMnO1xuaW1wb3J0IHsgSWRUb2tlbk1mYVJlc3BvbnNlIH0gZnJvbSAnLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vbW9kZWwvZW51bXMnO1xuXG5leHBvcnQgdHlwZSBNdWx0aUZhY3RvckVycm9yRGF0YSA9IE11bHRpRmFjdG9yRXJyb3JQdWJsaWNbJ2N1c3RvbURhdGEnXSAmIHtcbiAgX3NlcnZlclJlc3BvbnNlOiBJZFRva2VuTWZhUmVzcG9uc2U7XG59O1xuXG5leHBvcnQgY2xhc3MgTXVsdGlGYWN0b3JFcnJvclxuICBleHRlbmRzIEZpcmViYXNlRXJyb3JcbiAgaW1wbGVtZW50cyBNdWx0aUZhY3RvckVycm9yUHVibGljXG57XG4gIHJlYWRvbmx5IGN1c3RvbURhdGE6IE11bHRpRmFjdG9yRXJyb3JEYXRhO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGVycm9yOiBGaXJlYmFzZUVycm9yLFxuICAgIHJlYWRvbmx5IG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGUsXG4gICAgcmVhZG9ubHkgdXNlcj86IFVzZXJJbnRlcm5hbFxuICApIHtcbiAgICBzdXBlcihlcnJvci5jb2RlLCBlcnJvci5tZXNzYWdlKTtcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vTWljcm9zb2Z0L1R5cGVTY3JpcHQtd2lraS9ibG9iL21hc3Rlci9CcmVha2luZy1DaGFuZ2VzLm1kI2V4dGVuZGluZy1idWlsdC1pbnMtbGlrZS1lcnJvci1hcnJheS1hbmQtbWFwLW1heS1uby1sb25nZXItd29ya1xuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBNdWx0aUZhY3RvckVycm9yLnByb3RvdHlwZSk7XG4gICAgdGhpcy5jdXN0b21EYXRhID0ge1xuICAgICAgYXBwTmFtZTogYXV0aC5uYW1lLFxuICAgICAgdGVuYW50SWQ6IGF1dGgudGVuYW50SWQgPz8gdW5kZWZpbmVkLFxuICAgICAgX3NlcnZlclJlc3BvbnNlOiBlcnJvci5jdXN0b21EYXRhIS5fc2VydmVyUmVzcG9uc2UgYXMgSWRUb2tlbk1mYVJlc3BvbnNlLFxuICAgICAgb3BlcmF0aW9uVHlwZVxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgX2Zyb21FcnJvckFuZE9wZXJhdGlvbihcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgZXJyb3I6IEZpcmViYXNlRXJyb3IsXG4gICAgb3BlcmF0aW9uVHlwZTogT3BlcmF0aW9uVHlwZSxcbiAgICB1c2VyPzogVXNlckludGVybmFsXG4gICk6IE11bHRpRmFjdG9yRXJyb3Ige1xuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JFcnJvcihhdXRoLCBlcnJvciwgb3BlcmF0aW9uVHlwZSwgdXNlcik7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9wcm9jZXNzQ3JlZGVudGlhbFNhdmluZ01mYUNvbnRleHRJZk5lY2Vzc2FyeShcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICBvcGVyYXRpb25UeXBlOiBPcGVyYXRpb25UeXBlLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgdXNlcj86IFVzZXJJbnRlcm5hbFxuKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgY29uc3QgaWRUb2tlblByb3ZpZGVyID1cbiAgICBvcGVyYXRpb25UeXBlID09PSBPcGVyYXRpb25UeXBlLlJFQVVUSEVOVElDQVRFXG4gICAgICA/IGNyZWRlbnRpYWwuX2dldFJlYXV0aGVudGljYXRpb25SZXNvbHZlcihhdXRoKVxuICAgICAgOiBjcmVkZW50aWFsLl9nZXRJZFRva2VuUmVzcG9uc2UoYXV0aCk7XG5cbiAgcmV0dXJuIGlkVG9rZW5Qcm92aWRlci5jYXRjaChlcnJvciA9PiB7XG4gICAgaWYgKGVycm9yLmNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5NRkFfUkVRVUlSRUR9YCkge1xuICAgICAgdGhyb3cgTXVsdGlGYWN0b3JFcnJvci5fZnJvbUVycm9yQW5kT3BlcmF0aW9uKFxuICAgICAgICBhdXRoLFxuICAgICAgICBlcnJvcixcbiAgICAgICAgb3BlcmF0aW9uVHlwZSxcbiAgICAgICAgdXNlclxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aHJvdyBlcnJvcjtcbiAgfSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlckFzc29jaWF0ZWRPYmplY3Qge1xuICBwcm92aWRlcklkPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRha2VzIGEgc2V0IG9mIFVzZXJJbmZvIHByb3ZpZGVyIGRhdGEgYW5kIGNvbnZlcnRzIGl0IHRvIGEgc2V0IG9mIG5hbWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlckRhdGFBc05hbWVzPFQgZXh0ZW5kcyBQcm92aWRlckFzc29jaWF0ZWRPYmplY3Q+KFxuICBwcm92aWRlckRhdGE6IFRbXVxuKTogU2V0PHN0cmluZz4ge1xuICByZXR1cm4gbmV3IFNldChcbiAgICBwcm92aWRlckRhdGFcbiAgICAgIC5tYXAoKHsgcHJvdmlkZXJJZCB9KSA9PiBwcm92aWRlcklkKVxuICAgICAgLmZpbHRlcihwaWQgPT4gISFwaWQpIGFzIHN0cmluZ1tdXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IGRlbGV0ZUxpbmtlZEFjY291bnRzIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IFVzZXJJbnRlcm5hbCwgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuLi9jcmVkZW50aWFscyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBwcm92aWRlckRhdGFBc05hbWVzIH0gZnJvbSAnLi4vdXRpbC9wcm92aWRlcnMnO1xuaW1wb3J0IHsgX2xvZ291dElmSW52YWxpZGF0ZWQgfSBmcm9tICcuL2ludmFsaWRhdGlvbic7XG5pbXBvcnQgeyBfcmVsb2FkV2l0aG91dFNhdmluZyB9IGZyb20gJy4vcmVsb2FkJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW1wbCB9IGZyb20gJy4vdXNlcl9jcmVkZW50aWFsX2ltcGwnO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgT3BlcmF0aW9uVHlwZSwgUHJvdmlkZXJJZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuLyoqXG4gKiBVbmxpbmtzIGEgcHJvdmlkZXIgZnJvbSBhIHVzZXIgYWNjb3VudC5cbiAqXG4gKiBAcGFyYW0gdXNlciAtIFRoZSB1c2VyLlxuICogQHBhcmFtIHByb3ZpZGVySWQgLSBUaGUgcHJvdmlkZXIgdG8gdW5saW5rLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVubGluayh1c2VyOiBVc2VyLCBwcm92aWRlcklkOiBzdHJpbmcpOiBQcm9taXNlPFVzZXI+IHtcbiAgY29uc3QgdXNlckludGVybmFsID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbDtcbiAgYXdhaXQgX2Fzc2VydExpbmtlZFN0YXR1cyh0cnVlLCB1c2VySW50ZXJuYWwsIHByb3ZpZGVySWQpO1xuICBjb25zdCB7IHByb3ZpZGVyVXNlckluZm8gfSA9IGF3YWl0IGRlbGV0ZUxpbmtlZEFjY291bnRzKHVzZXJJbnRlcm5hbC5hdXRoLCB7XG4gICAgaWRUb2tlbjogYXdhaXQgdXNlckludGVybmFsLmdldElkVG9rZW4oKSxcbiAgICBkZWxldGVQcm92aWRlcjogW3Byb3ZpZGVySWRdXG4gIH0pO1xuXG4gIGNvbnN0IHByb3ZpZGVyc0xlZnQgPSBwcm92aWRlckRhdGFBc05hbWVzKHByb3ZpZGVyVXNlckluZm8gfHwgW10pO1xuXG4gIHVzZXJJbnRlcm5hbC5wcm92aWRlckRhdGEgPSB1c2VySW50ZXJuYWwucHJvdmlkZXJEYXRhLmZpbHRlcihwZCA9PlxuICAgIHByb3ZpZGVyc0xlZnQuaGFzKHBkLnByb3ZpZGVySWQpXG4gICk7XG4gIGlmICghcHJvdmlkZXJzTGVmdC5oYXMoUHJvdmlkZXJJZC5QSE9ORSkpIHtcbiAgICB1c2VySW50ZXJuYWwucGhvbmVOdW1iZXIgPSBudWxsO1xuICB9XG5cbiAgYXdhaXQgdXNlckludGVybmFsLmF1dGguX3BlcnNpc3RVc2VySWZDdXJyZW50KHVzZXJJbnRlcm5hbCk7XG4gIHJldHVybiB1c2VySW50ZXJuYWw7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBfbGluayhcbiAgdXNlcjogVXNlckludGVybmFsLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgYnlwYXNzQXV0aFN0YXRlID0gZmFsc2Vcbik6IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbnRlcm5hbD4ge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgIHVzZXIsXG4gICAgY3JlZGVudGlhbC5fbGlua1RvSWRUb2tlbih1c2VyLmF1dGgsIGF3YWl0IHVzZXIuZ2V0SWRUb2tlbigpKSxcbiAgICBieXBhc3NBdXRoU3RhdGVcbiAgKTtcbiAgcmV0dXJuIFVzZXJDcmVkZW50aWFsSW1wbC5fZm9yT3BlcmF0aW9uKHVzZXIsIE9wZXJhdGlvblR5cGUuTElOSywgcmVzcG9uc2UpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX2Fzc2VydExpbmtlZFN0YXR1cyhcbiAgZXhwZWN0ZWQ6IGJvb2xlYW4sXG4gIHVzZXI6IFVzZXJJbnRlcm5hbCxcbiAgcHJvdmlkZXI6IHN0cmluZ1xuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IF9yZWxvYWRXaXRob3V0U2F2aW5nKHVzZXIpO1xuICBjb25zdCBwcm92aWRlcklkcyA9IHByb3ZpZGVyRGF0YUFzTmFtZXModXNlci5wcm92aWRlckRhdGEpO1xuXG4gIGNvbnN0IGNvZGUgPVxuICAgIGV4cGVjdGVkID09PSBmYWxzZVxuICAgICAgPyBBdXRoRXJyb3JDb2RlLlBST1ZJREVSX0FMUkVBRFlfTElOS0VEXG4gICAgICA6IEF1dGhFcnJvckNvZGUuTk9fU1VDSF9QUk9WSURFUjtcbiAgX2Fzc2VydChwcm92aWRlcklkcy5oYXMocHJvdmlkZXIpID09PSBleHBlY3RlZCwgdXNlci5hdXRoLCBjb2RlKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgX3Byb2Nlc3NDcmVkZW50aWFsU2F2aW5nTWZhQ29udGV4dElmTmVjZXNzYXJ5IH0gZnJvbSAnLi4vLi4vbWZhL21mYV9lcnJvcic7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4uL2NyZWRlbnRpYWxzJztcbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCwgX2ZhaWwgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfcGFyc2VUb2tlbiB9IGZyb20gJy4vaWRfdG9rZW5fcmVzdWx0JztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbXBsIH0gZnJvbSAnLi91c2VyX2NyZWRlbnRpYWxfaW1wbCc7XG5pbXBvcnQgeyBfaXNGaXJlYmFzZVNlcnZlckFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvYXNzZXJ0JztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9yZWF1dGhlbnRpY2F0ZShcbiAgdXNlcjogVXNlckludGVybmFsLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgYnlwYXNzQXV0aFN0YXRlID0gZmFsc2Vcbik6IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbXBsPiB7XG4gIGNvbnN0IHsgYXV0aCB9ID0gdXNlcjtcbiAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKGF1dGgpXG4gICAgKTtcbiAgfVxuICBjb25zdCBvcGVyYXRpb25UeXBlID0gT3BlcmF0aW9uVHlwZS5SRUFVVEhFTlRJQ0FURTtcblxuICB0cnkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQoXG4gICAgICB1c2VyLFxuICAgICAgX3Byb2Nlc3NDcmVkZW50aWFsU2F2aW5nTWZhQ29udGV4dElmTmVjZXNzYXJ5KFxuICAgICAgICBhdXRoLFxuICAgICAgICBvcGVyYXRpb25UeXBlLFxuICAgICAgICBjcmVkZW50aWFsLFxuICAgICAgICB1c2VyXG4gICAgICApLFxuICAgICAgYnlwYXNzQXV0aFN0YXRlXG4gICAgKTtcbiAgICBfYXNzZXJ0KHJlc3BvbnNlLmlkVG9rZW4sIGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIGNvbnN0IHBhcnNlZCA9IF9wYXJzZVRva2VuKHJlc3BvbnNlLmlkVG9rZW4pO1xuICAgIF9hc3NlcnQocGFyc2VkLCBhdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcblxuICAgIGNvbnN0IHsgc3ViOiBsb2NhbElkIH0gPSBwYXJzZWQ7XG4gICAgX2Fzc2VydCh1c2VyLnVpZCA9PT0gbG9jYWxJZCwgYXV0aCwgQXV0aEVycm9yQ29kZS5VU0VSX01JU01BVENIKTtcblxuICAgIHJldHVybiBVc2VyQ3JlZGVudGlhbEltcGwuX2Zvck9wZXJhdGlvbih1c2VyLCBvcGVyYXRpb25UeXBlLCByZXNwb25zZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBDb252ZXJ0IHVzZXIgZGVsZXRlZCBlcnJvciBpbnRvIHVzZXIgbWlzbWF0Y2hcbiAgICBpZiAoKGUgYXMgRmlyZWJhc2VFcnJvcik/LmNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5VU0VSX0RFTEVURUR9YCkge1xuICAgICAgX2ZhaWwoYXV0aCwgQXV0aEVycm9yQ29kZS5VU0VSX01JU01BVENIKTtcbiAgICB9XG4gICAgdGhyb3cgZTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsLCBBdXRoLCBVc2VyIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgX3Byb2Nlc3NDcmVkZW50aWFsU2F2aW5nTWZhQ29udGV4dElmTmVjZXNzYXJ5IH0gZnJvbSAnLi4vLi4vbWZhL21mYV9lcnJvcic7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7IFVzZXJJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuLi9jcmVkZW50aWFscyc7XG5pbXBvcnQgeyBfYXNzZXJ0TGlua2VkU3RhdHVzLCBfbGluayB9IGZyb20gJy4uL3VzZXIvbGlua191bmxpbmsnO1xuaW1wb3J0IHsgX3JlYXV0aGVudGljYXRlIH0gZnJvbSAnLi4vdXNlci9yZWF1dGhlbnRpY2F0ZSc7XG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbEltcGwgfSBmcm9tICcuLi91c2VyL3VzZXJfY3JlZGVudGlhbF9pbXBsJztcbmltcG9ydCB7IF9jYXN0QXV0aCB9IGZyb20gJy4uL2F1dGgvYXV0aF9pbXBsJztcbmltcG9ydCB7IGdldE1vZHVsYXJJbnN0YW5jZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IE9wZXJhdGlvblR5cGUgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5pbXBvcnQgeyBfaXNGaXJlYmFzZVNlcnZlckFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvYXNzZXJ0JztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9zaWduSW5XaXRoQ3JlZGVudGlhbChcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgYnlwYXNzQXV0aFN0YXRlID0gZmFsc2Vcbik6IFByb21pc2U8VXNlckNyZWRlbnRpYWw+IHtcbiAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKGF1dGgpXG4gICAgKTtcbiAgfVxuICBjb25zdCBvcGVyYXRpb25UeXBlID0gT3BlcmF0aW9uVHlwZS5TSUdOX0lOO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9wcm9jZXNzQ3JlZGVudGlhbFNhdmluZ01mYUNvbnRleHRJZk5lY2Vzc2FyeShcbiAgICBhdXRoLFxuICAgIG9wZXJhdGlvblR5cGUsXG4gICAgY3JlZGVudGlhbFxuICApO1xuICBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IFVzZXJDcmVkZW50aWFsSW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoLFxuICAgIG9wZXJhdGlvblR5cGUsXG4gICAgcmVzcG9uc2VcbiAgKTtcblxuICBpZiAoIWJ5cGFzc0F1dGhTdGF0ZSkge1xuICAgIGF3YWl0IGF1dGguX3VwZGF0ZUN1cnJlbnRVc2VyKHVzZXJDcmVkZW50aWFsLnVzZXIpO1xuICB9XG4gIHJldHVybiB1c2VyQ3JlZGVudGlhbDtcbn1cblxuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzaWducyBpbiB3aXRoIHRoZSBnaXZlbiBjcmVkZW50aWFscy5cbiAqXG4gKiBAcmVtYXJrc1xuICogQW4ge0BsaW5rIEF1dGhQcm92aWRlcn0gY2FuIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGNyZWRlbnRpYWwuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGNyZWRlbnRpYWwgLSBUaGUgYXV0aCBjcmVkZW50aWFsLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbldpdGhDcmVkZW50aWFsKFxuICBhdXRoOiBBdXRoLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbFxuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICByZXR1cm4gX3NpZ25JbldpdGhDcmVkZW50aWFsKF9jYXN0QXV0aChhdXRoKSwgY3JlZGVudGlhbCk7XG59XG5cbi8qKlxuICogTGlua3MgdGhlIHVzZXIgYWNjb3VudCB3aXRoIHRoZSBnaXZlbiBjcmVkZW50aWFscy5cbiAqXG4gKiBAcmVtYXJrc1xuICogQW4ge0BsaW5rIEF1dGhQcm92aWRlcn0gY2FuIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGNyZWRlbnRpYWwuXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBjcmVkZW50aWFsIC0gVGhlIGF1dGggY3JlZGVudGlhbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaW5rV2l0aENyZWRlbnRpYWwoXG4gIHVzZXI6IFVzZXIsXG4gIGNyZWRlbnRpYWw6IEF1dGhDcmVkZW50aWFsXG4pOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbCA9IGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWw7XG5cbiAgYXdhaXQgX2Fzc2VydExpbmtlZFN0YXR1cyhmYWxzZSwgdXNlckludGVybmFsLCBjcmVkZW50aWFsLnByb3ZpZGVySWQpO1xuXG4gIHJldHVybiBfbGluayh1c2VySW50ZXJuYWwsIGNyZWRlbnRpYWwpO1xufVxuXG4vKipcbiAqIFJlLWF1dGhlbnRpY2F0ZXMgYSB1c2VyIHVzaW5nIGEgZnJlc2ggY3JlZGVudGlhbC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVXNlIGJlZm9yZSBvcGVyYXRpb25zIHN1Y2ggYXMge0BsaW5rIHVwZGF0ZVBhc3N3b3JkfSB0aGF0IHJlcXVpcmUgdG9rZW5zIGZyb20gcmVjZW50IHNpZ24taW5cbiAqIGF0dGVtcHRzLiBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byByZWNvdmVyIGZyb20gYSBgQ1JFREVOVElBTF9UT09fT0xEX0xPR0lOX0FHQUlOYCBlcnJvclxuICogb3IgYSBgVE9LRU5fRVhQSVJFRGAgZXJyb3IuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBvbiBhbnkge0BsaW5rIFVzZXJ9IHNpZ25lZCBpbiBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzXG4gKiBjcmVhdGVkIHdpdGggYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBjcmVkZW50aWFsIC0gVGhlIGF1dGggY3JlZGVudGlhbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWF1dGhlbnRpY2F0ZVdpdGhDcmVkZW50aWFsKFxuICB1c2VyOiBVc2VyLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbFxuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICByZXR1cm4gX3JlYXV0aGVudGljYXRlKGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWwsIGNyZWRlbnRpYWwpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEVuZHBvaW50LFxuICBIdHRwTWV0aG9kLFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIF9wZXJmb3JtU2lnbkluUmVxdWVzdFxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTaWduSW5XaXRoQ3VzdG9tVG9rZW5SZXF1ZXN0IHtcbiAgdG9rZW46IHN0cmluZztcbiAgcmV0dXJuU2VjdXJlVG9rZW46IGJvb2xlYW47XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhDdXN0b21Ub2tlblJlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHt9XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduSW5XaXRoQ3VzdG9tVG9rZW4oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25JbldpdGhDdXN0b21Ub2tlblJlcXVlc3Rcbik6IFByb21pc2U8U2lnbkluV2l0aEN1c3RvbVRva2VuUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtU2lnbkluUmVxdWVzdDxcbiAgICBTaWduSW5XaXRoQ3VzdG9tVG9rZW5SZXF1ZXN0LFxuICAgIFNpZ25JbldpdGhDdXN0b21Ub2tlblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9JTl9XSVRIX0NVU1RPTV9UT0tFTixcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoLCBVc2VyQ3JlZGVudGlhbCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IHNpZ25JbldpdGhDdXN0b21Ub2tlbiBhcyBnZXRJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vY3VzdG9tX3Rva2VuJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW1wbCB9IGZyb20gJy4uL3VzZXIvdXNlcl9jcmVkZW50aWFsX2ltcGwnO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vYXV0aC9hdXRoX2ltcGwnO1xuaW1wb3J0IHsgT3BlcmF0aW9uVHlwZSB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvciB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzaWducyBpbiB1c2luZyBhIGN1c3RvbSB0b2tlbi5cbiAqXG4gKiBAcmVtYXJrc1xuICogQ3VzdG9tIHRva2VucyBhcmUgdXNlZCB0byBpbnRlZ3JhdGUgRmlyZWJhc2UgQXV0aCB3aXRoIGV4aXN0aW5nIGF1dGggc3lzdGVtcywgYW5kIG11c3RcbiAqIGJlIGdlbmVyYXRlZCBieSBhbiBhdXRoIGJhY2tlbmQgdXNpbmcgdGhlXG4gKiB7QGxpbmsgaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3MvcmVmZXJlbmNlL2FkbWluL25vZGUvYWRtaW4uYXV0aC5BdXRoI2NyZWF0ZWN1c3RvbXRva2VuIHwgY3JlYXRlQ3VzdG9tVG9rZW59XG4gKiBtZXRob2QgaW4gdGhlIHtAbGluayBodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy9hdXRoL2FkbWluIHwgQWRtaW4gU0RLfSAuXG4gKlxuICogRmFpbHMgd2l0aCBhbiBlcnJvciBpZiB0aGUgdG9rZW4gaXMgaW52YWxpZCwgZXhwaXJlZCwgb3Igbm90IGFjY2VwdGVkIGJ5IHRoZSBGaXJlYmFzZSBBdXRoIHNlcnZpY2UuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGN1c3RvbVRva2VuIC0gVGhlIGN1c3RvbSB0b2tlbiB0byBzaWduIGluIHdpdGguXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aEN1c3RvbVRva2VuKFxuICBhdXRoOiBBdXRoLFxuICBjdXN0b21Ub2tlbjogc3RyaW5nXG4pOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcChhdXRoLmFwcCkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcihhdXRoKVxuICAgICk7XG4gIH1cbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICBjb25zdCByZXNwb25zZTogSWRUb2tlblJlc3BvbnNlID0gYXdhaXQgZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGhJbnRlcm5hbCwge1xuICAgIHRva2VuOiBjdXN0b21Ub2tlbixcbiAgICByZXR1cm5TZWN1cmVUb2tlbjogdHJ1ZVxuICB9KTtcbiAgY29uc3QgY3JlZCA9IGF3YWl0IFVzZXJDcmVkZW50aWFsSW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgT3BlcmF0aW9uVHlwZS5TSUdOX0lOLFxuICAgIHJlc3BvbnNlXG4gICk7XG4gIGF3YWl0IGF1dGhJbnRlcm5hbC5fdXBkYXRlQ3VycmVudFVzZXIoY3JlZC51c2VyKTtcbiAgcmV0dXJuIGNyZWQ7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRmFjdG9ySWQsXG4gIE11bHRpRmFjdG9ySW5mbyxcbiAgUGhvbmVNdWx0aUZhY3RvckluZm8sXG4gIFRvdHBNdWx0aUZhY3RvckluZm9cbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7XG4gIFBob25lTWZhRW5yb2xsbWVudCxcbiAgTWZhRW5yb2xsbWVudCxcbiAgVG90cE1mYUVucm9sbG1lbnRcbn0gZnJvbSAnLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9tZmEnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2NvcmUvZXJyb3JzJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi9tb2RlbC9hdXRoJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE11bHRpRmFjdG9ySW5mb0ltcGwgaW1wbGVtZW50cyBNdWx0aUZhY3RvckluZm8ge1xuICByZWFkb25seSB1aWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZGlzcGxheU5hbWU/OiBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBlbnJvbGxtZW50VGltZTogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihyZWFkb25seSBmYWN0b3JJZDogRmFjdG9ySWQsIHJlc3BvbnNlOiBNZmFFbnJvbGxtZW50KSB7XG4gICAgdGhpcy51aWQgPSByZXNwb25zZS5tZmFFbnJvbGxtZW50SWQ7XG4gICAgdGhpcy5lbnJvbGxtZW50VGltZSA9IG5ldyBEYXRlKHJlc3BvbnNlLmVucm9sbGVkQXQpLnRvVVRDU3RyaW5nKCk7XG4gICAgdGhpcy5kaXNwbGF5TmFtZSA9IHJlc3BvbnNlLmRpc3BsYXlOYW1lO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGVucm9sbG1lbnQ6IE1mYUVucm9sbG1lbnRcbiAgKTogTXVsdGlGYWN0b3JJbmZvSW1wbCB7XG4gICAgaWYgKCdwaG9uZUluZm8nIGluIGVucm9sbG1lbnQpIHtcbiAgICAgIHJldHVybiBQaG9uZU11bHRpRmFjdG9ySW5mb0ltcGwuX2Zyb21TZXJ2ZXJSZXNwb25zZShhdXRoLCBlbnJvbGxtZW50KTtcbiAgICB9IGVsc2UgaWYgKCd0b3RwSW5mbycgaW4gZW5yb2xsbWVudCkge1xuICAgICAgcmV0dXJuIFRvdHBNdWx0aUZhY3RvckluZm9JbXBsLl9mcm9tU2VydmVyUmVzcG9uc2UoYXV0aCwgZW5yb2xsbWVudCk7XG4gICAgfVxuICAgIHJldHVybiBfZmFpbChhdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUGhvbmVNdWx0aUZhY3RvckluZm9JbXBsXG4gIGV4dGVuZHMgTXVsdGlGYWN0b3JJbmZvSW1wbFxuICBpbXBsZW1lbnRzIFBob25lTXVsdGlGYWN0b3JJbmZvXG57XG4gIHJlYWRvbmx5IHBob25lTnVtYmVyOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihyZXNwb25zZTogUGhvbmVNZmFFbnJvbGxtZW50KSB7XG4gICAgc3VwZXIoRmFjdG9ySWQuUEhPTkUsIHJlc3BvbnNlKTtcbiAgICB0aGlzLnBob25lTnVtYmVyID0gcmVzcG9uc2UucGhvbmVJbmZvO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgX2F1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBlbnJvbGxtZW50OiBNZmFFbnJvbGxtZW50XG4gICk6IFBob25lTXVsdGlGYWN0b3JJbmZvSW1wbCB7XG4gICAgcmV0dXJuIG5ldyBQaG9uZU11bHRpRmFjdG9ySW5mb0ltcGwoZW5yb2xsbWVudCBhcyBQaG9uZU1mYUVucm9sbG1lbnQpO1xuICB9XG59XG5leHBvcnQgY2xhc3MgVG90cE11bHRpRmFjdG9ySW5mb0ltcGxcbiAgZXh0ZW5kcyBNdWx0aUZhY3RvckluZm9JbXBsXG4gIGltcGxlbWVudHMgVG90cE11bHRpRmFjdG9ySW5mb1xue1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHJlc3BvbnNlOiBUb3RwTWZhRW5yb2xsbWVudCkge1xuICAgIHN1cGVyKEZhY3RvcklkLlRPVFAsIHJlc3BvbnNlKTtcbiAgfVxuXG4gIHN0YXRpYyBfZnJvbVNlcnZlclJlc3BvbnNlKFxuICAgIF9hdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgZW5yb2xsbWVudDogTWZhRW5yb2xsbWVudFxuICApOiBUb3RwTXVsdGlGYWN0b3JJbmZvSW1wbCB7XG4gICAgcmV0dXJuIG5ldyBUb3RwTXVsdGlGYWN0b3JJbmZvSW1wbChlbnJvbGxtZW50IGFzIFRvdHBNZmFFbnJvbGxtZW50KTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEFjdGlvbkNvZGVTZXR0aW5ncywgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IEdldE9vYkNvZGVSZXF1ZXN0IH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0KFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBHZXRPb2JDb2RlUmVxdWVzdCxcbiAgYWN0aW9uQ29kZVNldHRpbmdzOiBBY3Rpb25Db2RlU2V0dGluZ3Ncbik6IHZvaWQge1xuICBfYXNzZXJ0KFxuICAgIGFjdGlvbkNvZGVTZXR0aW5ncy51cmw/Lmxlbmd0aCA+IDAsXG4gICAgYXV0aCxcbiAgICBBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09OVElOVUVfVVJJXG4gICk7XG4gIF9hc3NlcnQoXG4gICAgdHlwZW9mIGFjdGlvbkNvZGVTZXR0aW5ncy5keW5hbWljTGlua0RvbWFpbiA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgIGFjdGlvbkNvZGVTZXR0aW5ncy5keW5hbWljTGlua0RvbWFpbi5sZW5ndGggPiAwLFxuICAgIGF1dGgsXG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX0RZTkFNSUNfTElOS19ET01BSU5cbiAgKTtcbiAgX2Fzc2VydChcbiAgICB0eXBlb2YgYWN0aW9uQ29kZVNldHRpbmdzLmxpbmtEb21haW4gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICBhY3Rpb25Db2RlU2V0dGluZ3MubGlua0RvbWFpbi5sZW5ndGggPiAwLFxuICAgIGF1dGgsXG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX0hPU1RJTkdfTElOS19ET01BSU5cbiAgKTtcblxuICByZXF1ZXN0LmNvbnRpbnVlVXJsID0gYWN0aW9uQ29kZVNldHRpbmdzLnVybDtcbiAgcmVxdWVzdC5keW5hbWljTGlua0RvbWFpbiA9IGFjdGlvbkNvZGVTZXR0aW5ncy5keW5hbWljTGlua0RvbWFpbjtcbiAgcmVxdWVzdC5saW5rRG9tYWluID0gYWN0aW9uQ29kZVNldHRpbmdzLmxpbmtEb21haW47XG4gIHJlcXVlc3QuY2FuSGFuZGxlQ29kZUluQXBwID0gYWN0aW9uQ29kZVNldHRpbmdzLmhhbmRsZUNvZGVJbkFwcDtcblxuICBpZiAoYWN0aW9uQ29kZVNldHRpbmdzLmlPUykge1xuICAgIF9hc3NlcnQoXG4gICAgICBhY3Rpb25Db2RlU2V0dGluZ3MuaU9TLmJ1bmRsZUlkLmxlbmd0aCA+IDAsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX0lPU19CVU5ETEVfSURcbiAgICApO1xuICAgIHJlcXVlc3QuaU9TQnVuZGxlSWQgPSBhY3Rpb25Db2RlU2V0dGluZ3MuaU9TLmJ1bmRsZUlkO1xuICB9XG5cbiAgaWYgKGFjdGlvbkNvZGVTZXR0aW5ncy5hbmRyb2lkKSB7XG4gICAgX2Fzc2VydChcbiAgICAgIGFjdGlvbkNvZGVTZXR0aW5ncy5hbmRyb2lkLnBhY2thZ2VOYW1lLmxlbmd0aCA+IDAsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX0FORFJPSURfUEFDS0FHRV9OQU1FXG4gICAgKTtcbiAgICByZXF1ZXN0LmFuZHJvaWRJbnN0YWxsQXBwID0gYWN0aW9uQ29kZVNldHRpbmdzLmFuZHJvaWQuaW5zdGFsbEFwcDtcbiAgICByZXF1ZXN0LmFuZHJvaWRNaW5pbXVtVmVyc2lvbkNvZGUgPVxuICAgICAgYWN0aW9uQ29kZVNldHRpbmdzLmFuZHJvaWQubWluaW11bVZlcnNpb247XG4gICAgcmVxdWVzdC5hbmRyb2lkUGFja2FnZU5hbWUgPSBhY3Rpb25Db2RlU2V0dGluZ3MuYW5kcm9pZC5wYWNrYWdlTmFtZTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEFjdGlvbkNvZGVJbmZvLFxuICBBY3Rpb25Db2RlT3BlcmF0aW9uLFxuICBBY3Rpb25Db2RlU2V0dGluZ3MsXG4gIEF1dGgsXG4gIFVzZXJDcmVkZW50aWFsXG59IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCAqIGFzIGFjY291bnQgZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9lbWFpbF9hbmRfcGFzc3dvcmQnO1xuaW1wb3J0ICogYXMgYXV0aGVudGljYXRpb24gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBzaWduVXAsIFNpZ25VcFJlcXVlc3QgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vc2lnbl91cCc7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckluZm9JbXBsIH0gZnJvbSAnLi4vLi4vbWZhL21mYV9pbmZvJztcbmltcG9ydCB7IEVtYWlsQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi4vcHJvdmlkZXJzL2VtYWlsJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW1wbCB9IGZyb20gJy4uL3VzZXIvdXNlcl9jcmVkZW50aWFsX2ltcGwnO1xuaW1wb3J0IHtcbiAgX2Fzc2VydCxcbiAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3Jcbn0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdCB9IGZyb20gJy4vYWN0aW9uX2NvZGVfc2V0dGluZ3MnO1xuaW1wb3J0IHsgc2lnbkluV2l0aENyZWRlbnRpYWwgfSBmcm9tICcuL2NyZWRlbnRpYWwnO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vYXV0aC9hdXRoX2ltcGwnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgaGFuZGxlUmVjYXB0Y2hhRmxvdyB9IGZyb20gJy4uLy4uL3BsYXRmb3JtX2Jyb3dzZXIvcmVjYXB0Y2hhL3JlY2FwdGNoYV9lbnRlcnByaXNlX3ZlcmlmaWVyJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7XG4gIFJlY2FwdGNoYUFjdGlvbk5hbWUsXG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYUF1dGhQcm92aWRlclxufSBmcm9tICcuLi8uLi9hcGknO1xuaW1wb3J0IHsgX2lzRmlyZWJhc2VTZXJ2ZXJBcHAgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBwYXNzd29yZCBwb2xpY3kgY2FjaGVkIGluIHRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UgaWYgYSBwb2xpY3kgaXMgYWxyZWFkeVxuICogY2FjaGVkIGZvciB0aGUgcHJvamVjdCBvciB0ZW5hbnQuXG4gKlxuICogQHJlbWFya3NcbiAqIFdlIG9ubHkgZmV0Y2ggdGhlIHBhc3N3b3JkIHBvbGljeSBpZiB0aGUgcGFzc3dvcmQgZGlkIG5vdCBtZWV0IHBvbGljeSByZXF1aXJlbWVudHMgYW5kXG4gKiB0aGVyZSBpcyBhbiBleGlzdGluZyBwb2xpY3kgY2FjaGVkLiBBIGRldmVsb3BlciBtdXN0IGNhbGwgdmFsaWRhdGVQYXNzd29yZCBhdCBsZWFzdFxuICogb25jZSBmb3IgdGhlIGNhY2hlIHRvIGJlIGF1dG9tYXRpY2FsbHkgdXBkYXRlZC5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVjYWNoZVBhc3N3b3JkUG9saWN5KGF1dGg6IEF1dGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICBpZiAoYXV0aEludGVybmFsLl9nZXRQYXNzd29yZFBvbGljeUludGVybmFsKCkpIHtcbiAgICBhd2FpdCBhdXRoSW50ZXJuYWwuX3VwZGF0ZVBhc3N3b3JkUG9saWN5KCk7XG4gIH1cbn1cblxuLyoqXG4gKiBTZW5kcyBhIHBhc3N3b3JkIHJlc2V0IGVtYWlsIHRvIHRoZSBnaXZlbiBlbWFpbCBhZGRyZXNzLiBUaGlzIG1ldGhvZCBkb2VzIG5vdCB0aHJvdyBhbiBlcnJvciB3aGVuXG4gKiB0aGVyZSdzIG5vIHVzZXIgYWNjb3VudCB3aXRoIHRoZSBnaXZlbiBlbWFpbCBhZGRyZXNzIGFuZFxuICoge0BsaW5rIGh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9pZGVudGl0eS1wbGF0Zm9ybS9kb2NzL2FkbWluL2VtYWlsLWVudW1lcmF0aW9uLXByb3RlY3Rpb24gfCBFbWFpbCBFbnVtZXJhdGlvbiBQcm90ZWN0aW9ufVxuICogaXMgZW5hYmxlZC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVG8gY29tcGxldGUgdGhlIHBhc3N3b3JkIHJlc2V0LCBjYWxsIHtAbGluayBjb25maXJtUGFzc3dvcmRSZXNldH0gd2l0aCB0aGUgY29kZSBzdXBwbGllZCBpblxuICogdGhlIGVtYWlsIHNlbnQgdG8gdGhlIHVzZXIsIGFsb25nIHdpdGggdGhlIG5ldyBwYXNzd29yZCBzcGVjaWZpZWQgYnkgdGhlIHVzZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGNvbnN0IGFjdGlvbkNvZGVTZXR0aW5ncyA9IHtcbiAqICAgdXJsOiAnaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vP2VtYWlsPXVzZXJAZXhhbXBsZS5jb20nLFxuICogICBpT1M6IHtcbiAqICAgICAgYnVuZGxlSWQ6ICdjb20uZXhhbXBsZS5pb3MnXG4gKiAgIH0sXG4gKiAgIGFuZHJvaWQ6IHtcbiAqICAgICBwYWNrYWdlTmFtZTogJ2NvbS5leGFtcGxlLmFuZHJvaWQnLFxuICogICAgIGluc3RhbGxBcHA6IHRydWUsXG4gKiAgICAgbWluaW11bVZlcnNpb246ICcxMidcbiAqICAgfSxcbiAqICAgaGFuZGxlQ29kZUluQXBwOiB0cnVlXG4gKiB9O1xuICogYXdhaXQgc2VuZFBhc3N3b3JkUmVzZXRFbWFpbChhdXRoLCAndXNlckBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gY29kZSBmcm9tIHVzZXIuXG4gKiBhd2FpdCBjb25maXJtUGFzc3dvcmRSZXNldCgndXNlckBleGFtcGxlLmNvbScsIGNvZGUpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVtYWlsIC0gVGhlIHVzZXIncyBlbWFpbCBhZGRyZXNzLlxuICogQHBhcmFtIGFjdGlvbkNvZGVTZXR0aW5ncyAtIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVNldHRpbmdzfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kUGFzc3dvcmRSZXNldEVtYWlsKFxuICBhdXRoOiBBdXRoLFxuICBlbWFpbDogc3RyaW5nLFxuICBhY3Rpb25Db2RlU2V0dGluZ3M/OiBBY3Rpb25Db2RlU2V0dGluZ3Ncbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG4gIGNvbnN0IHJlcXVlc3Q6IGF1dGhlbnRpY2F0aW9uLlBhc3N3b3JkUmVzZXRSZXF1ZXN0ID0ge1xuICAgIHJlcXVlc3RUeXBlOiBBY3Rpb25Db2RlT3BlcmF0aW9uLlBBU1NXT1JEX1JFU0VULFxuICAgIGVtYWlsLFxuICAgIGNsaWVudFR5cGU6IFJlY2FwdGNoYUNsaWVudFR5cGUuV0VCXG4gIH07XG4gIGlmIChhY3Rpb25Db2RlU2V0dGluZ3MpIHtcbiAgICBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0KGF1dGhJbnRlcm5hbCwgcmVxdWVzdCwgYWN0aW9uQ29kZVNldHRpbmdzKTtcbiAgfVxuICBhd2FpdCBoYW5kbGVSZWNhcHRjaGFGbG93KFxuICAgIGF1dGhJbnRlcm5hbCxcbiAgICByZXF1ZXN0LFxuICAgIFJlY2FwdGNoYUFjdGlvbk5hbWUuR0VUX09PQl9DT0RFLFxuICAgIGF1dGhlbnRpY2F0aW9uLnNlbmRQYXNzd29yZFJlc2V0RW1haWwsXG4gICAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyLkVNQUlMX1BBU1NXT1JEX1BST1ZJREVSXG4gICk7XG59XG5cbi8qKlxuICogQ29tcGxldGVzIHRoZSBwYXNzd29yZCByZXNldCBwcm9jZXNzLCBnaXZlbiBhIGNvbmZpcm1hdGlvbiBjb2RlIGFuZCBuZXcgcGFzc3dvcmQuXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIG9vYkNvZGUgLSBBIGNvbmZpcm1hdGlvbiBjb2RlIHNlbnQgdG8gdGhlIHVzZXIuXG4gKiBAcGFyYW0gbmV3UGFzc3dvcmQgLSBUaGUgbmV3IHBhc3N3b3JkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbmZpcm1QYXNzd29yZFJlc2V0KFxuICBhdXRoOiBBdXRoLFxuICBvb2JDb2RlOiBzdHJpbmcsXG4gIG5ld1Bhc3N3b3JkOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBhY2NvdW50XG4gICAgLnJlc2V0UGFzc3dvcmQoZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpLCB7XG4gICAgICBvb2JDb2RlLFxuICAgICAgbmV3UGFzc3dvcmRcbiAgICB9KVxuICAgIC5jYXRjaChhc3luYyBlcnJvciA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGVycm9yLmNvZGUgPT09XG4gICAgICAgIGBhdXRoLyR7QXV0aEVycm9yQ29kZS5QQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UU31gXG4gICAgICApIHtcbiAgICAgICAgdm9pZCByZWNhY2hlUGFzc3dvcmRQb2xpY3koYXV0aCk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xuICAvLyBEbyBub3QgcmV0dXJuIHRoZSBlbWFpbC5cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGEgdmVyaWZpY2F0aW9uIGNvZGUgc2VudCB0byB0aGUgdXNlciBieSBlbWFpbCBvciBvdGhlciBvdXQtb2YtYmFuZCBtZWNoYW5pc20uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIG9vYkNvZGUgLSBBIHZlcmlmaWNhdGlvbiBjb2RlIHNlbnQgdG8gdGhlIHVzZXIuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXBwbHlBY3Rpb25Db2RlKFxuICBhdXRoOiBBdXRoLFxuICBvb2JDb2RlOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBhY2NvdW50LmFwcGx5QWN0aW9uQ29kZShnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksIHsgb29iQ29kZSB9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSB2ZXJpZmljYXRpb24gY29kZSBzZW50IHRvIHRoZSB1c2VyIGJ5IGVtYWlsIG9yIG90aGVyIG91dC1vZi1iYW5kIG1lY2hhbmlzbS5cbiAqXG4gKiBAcmV0dXJucyBtZXRhZGF0YSBhYm91dCB0aGUgY29kZS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gb29iQ29kZSAtIEEgdmVyaWZpY2F0aW9uIGNvZGUgc2VudCB0byB0aGUgdXNlci5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja0FjdGlvbkNvZGUoXG4gIGF1dGg6IEF1dGgsXG4gIG9vYkNvZGU6IHN0cmluZ1xuKTogUHJvbWlzZTxBY3Rpb25Db2RlSW5mbz4ge1xuICBjb25zdCBhdXRoTW9kdWxhciA9IGdldE1vZHVsYXJJbnN0YW5jZShhdXRoKTtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhY2NvdW50LnJlc2V0UGFzc3dvcmQoYXV0aE1vZHVsYXIsIHsgb29iQ29kZSB9KTtcblxuICAvLyBFbWFpbCBjb3VsZCBiZSBlbXB0eSBvbmx5IGlmIHRoZSByZXF1ZXN0IHR5cGUgaXMgRU1BSUxfU0lHTklOIG9yXG4gIC8vIFZFUklGWV9BTkRfQ0hBTkdFX0VNQUlMLlxuICAvLyBOZXcgZW1haWwgc2hvdWxkIG5vdCBiZSBlbXB0eSBpZiB0aGUgcmVxdWVzdCB0eXBlIGlzXG4gIC8vIFZFUklGWV9BTkRfQ0hBTkdFX0VNQUlMLlxuICAvLyBNdWx0aS1mYWN0b3IgaW5mbyBjb3VsZCBub3QgYmUgZW1wdHkgaWYgdGhlIHJlcXVlc3QgdHlwZSBpc1xuICAvLyBSRVZFUlRfU0VDT05EX0ZBQ1RPUl9BRERJVElPTi5cbiAgY29uc3Qgb3BlcmF0aW9uID0gcmVzcG9uc2UucmVxdWVzdFR5cGU7XG4gIF9hc3NlcnQob3BlcmF0aW9uLCBhdXRoTW9kdWxhciwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gIHN3aXRjaCAob3BlcmF0aW9uKSB7XG4gICAgY2FzZSBBY3Rpb25Db2RlT3BlcmF0aW9uLkVNQUlMX1NJR05JTjpcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfQU5EX0NIQU5HRV9FTUFJTDpcbiAgICAgIF9hc3NlcnQocmVzcG9uc2UubmV3RW1haWwsIGF1dGhNb2R1bGFyLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQWN0aW9uQ29kZU9wZXJhdGlvbi5SRVZFUlRfU0VDT05EX0ZBQ1RPUl9BRERJVElPTjpcbiAgICAgIF9hc3NlcnQocmVzcG9uc2UubWZhSW5mbywgYXV0aE1vZHVsYXIsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIC8vIGZhbGwgdGhyb3VnaFxuICAgIGRlZmF1bHQ6XG4gICAgICBfYXNzZXJ0KHJlc3BvbnNlLmVtYWlsLCBhdXRoTW9kdWxhciwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gIH1cblxuICAvLyBUaGUgbXVsdGktZmFjdG9yIGluZm8gZm9yIHJldmVydCBzZWNvbmQgZmFjdG9yIGFkZGl0aW9uXG4gIGxldCBtdWx0aUZhY3RvckluZm86IE11bHRpRmFjdG9ySW5mb0ltcGwgfCBudWxsID0gbnVsbDtcbiAgaWYgKHJlc3BvbnNlLm1mYUluZm8pIHtcbiAgICBtdWx0aUZhY3RvckluZm8gPSBNdWx0aUZhY3RvckluZm9JbXBsLl9mcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgICBfY2FzdEF1dGgoYXV0aE1vZHVsYXIpLFxuICAgICAgcmVzcG9uc2UubWZhSW5mb1xuICAgICk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGRhdGE6IHtcbiAgICAgIGVtYWlsOlxuICAgICAgICAocmVzcG9uc2UucmVxdWVzdFR5cGUgPT09IEFjdGlvbkNvZGVPcGVyYXRpb24uVkVSSUZZX0FORF9DSEFOR0VfRU1BSUxcbiAgICAgICAgICA/IHJlc3BvbnNlLm5ld0VtYWlsXG4gICAgICAgICAgOiByZXNwb25zZS5lbWFpbCkgfHwgbnVsbCxcbiAgICAgIHByZXZpb3VzRW1haWw6XG4gICAgICAgIChyZXNwb25zZS5yZXF1ZXN0VHlwZSA9PT0gQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfQU5EX0NIQU5HRV9FTUFJTFxuICAgICAgICAgID8gcmVzcG9uc2UuZW1haWxcbiAgICAgICAgICA6IHJlc3BvbnNlLm5ld0VtYWlsKSB8fCBudWxsLFxuICAgICAgbXVsdGlGYWN0b3JJbmZvXG4gICAgfSxcbiAgICBvcGVyYXRpb25cbiAgfTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSBwYXNzd29yZCByZXNldCBjb2RlIHNlbnQgdG8gdGhlIHVzZXIgYnkgZW1haWwgb3Igb3RoZXIgb3V0LW9mLWJhbmQgbWVjaGFuaXNtLlxuICpcbiAqIEByZXR1cm5zIHRoZSB1c2VyJ3MgZW1haWwgYWRkcmVzcyBpZiB2YWxpZC5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gY29kZSAtIEEgdmVyaWZpY2F0aW9uIGNvZGUgc2VudCB0byB0aGUgdXNlci5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlQYXNzd29yZFJlc2V0Q29kZShcbiAgYXV0aDogQXV0aCxcbiAgY29kZTogc3RyaW5nXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IGNoZWNrQWN0aW9uQ29kZShnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksIGNvZGUpO1xuICAvLyBFbWFpbCBzaG91bGQgYWx3YXlzIGJlIHByZXNlbnQgc2luY2UgYSBjb2RlIHdhcyBzZW50IHRvIGl0XG4gIHJldHVybiBkYXRhLmVtYWlsITtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHVzZXIgYWNjb3VudCBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBlbWFpbCBhZGRyZXNzIGFuZCBwYXNzd29yZC5cbiAqXG4gKiBAcmVtYXJrc1xuICogT24gc3VjY2Vzc2Z1bCBjcmVhdGlvbiBvZiB0aGUgdXNlciBhY2NvdW50LCB0aGlzIHVzZXIgd2lsbCBhbHNvIGJlIHNpZ25lZCBpbiB0byB5b3VyIGFwcGxpY2F0aW9uLlxuICpcbiAqIFVzZXIgYWNjb3VudCBjcmVhdGlvbiBjYW4gZmFpbCBpZiB0aGUgYWNjb3VudCBhbHJlYWR5IGV4aXN0cyBvciB0aGUgcGFzc3dvcmQgaXMgaW52YWxpZC5cbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIG9uIHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBOb3RlOiBUaGUgZW1haWwgYWRkcmVzcyBhY3RzIGFzIGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSB1c2VyIGFuZCBlbmFibGVzIGFuIGVtYWlsLWJhc2VkXG4gKiBwYXNzd29yZCByZXNldC4gVGhpcyBmdW5jdGlvbiB3aWxsIGNyZWF0ZSBhIG5ldyB1c2VyIGFjY291bnQgYW5kIHNldCB0aGUgaW5pdGlhbCB1c2VyIHBhc3N3b3JkLlxuICpcbiAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqIEBwYXJhbSBlbWFpbCAtIFRoZSB1c2VyJ3MgZW1haWwgYWRkcmVzcy5cbiAqIEBwYXJhbSBwYXNzd29yZCAtIFRoZSB1c2VyJ3MgY2hvc2VuIHBhc3N3b3JkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZyxcbiAgcGFzc3dvcmQ6IHN0cmluZ1xuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAoYXV0aC5hcHApKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IoYXV0aClcbiAgICApO1xuICB9XG4gIGNvbnN0IGF1dGhJbnRlcm5hbCA9IF9jYXN0QXV0aChhdXRoKTtcbiAgY29uc3QgcmVxdWVzdDogU2lnblVwUmVxdWVzdCA9IHtcbiAgICByZXR1cm5TZWN1cmVUb2tlbjogdHJ1ZSxcbiAgICBlbWFpbCxcbiAgICBwYXNzd29yZCxcbiAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICB9O1xuICBjb25zdCBzaWduVXBSZXNwb25zZTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+ID0gaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgcmVxdWVzdCxcbiAgICBSZWNhcHRjaGFBY3Rpb25OYW1lLlNJR05fVVBfUEFTU1dPUkQsXG4gICAgc2lnblVwLFxuICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICApO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNpZ25VcFJlc3BvbnNlLmNhdGNoKGVycm9yID0+IHtcbiAgICBpZiAoXG4gICAgICBlcnJvci5jb2RlID09PSBgYXV0aC8ke0F1dGhFcnJvckNvZGUuUEFTU1dPUkRfRE9FU19OT1RfTUVFVF9SRVFVSVJFTUVOVFN9YFxuICAgICkge1xuICAgICAgdm9pZCByZWNhY2hlUGFzc3dvcmRQb2xpY3koYXV0aCk7XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyb3I7XG4gIH0pO1xuXG4gIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgVXNlckNyZWRlbnRpYWxJbXBsLl9mcm9tSWRUb2tlblJlc3BvbnNlKFxuICAgIGF1dGhJbnRlcm5hbCxcbiAgICBPcGVyYXRpb25UeXBlLlNJR05fSU4sXG4gICAgcmVzcG9uc2VcbiAgKTtcbiAgYXdhaXQgYXV0aEludGVybmFsLl91cGRhdGVDdXJyZW50VXNlcih1c2VyQ3JlZGVudGlhbC51c2VyKTtcblxuICByZXR1cm4gdXNlckNyZWRlbnRpYWw7XG59XG5cbi8qKlxuICogQXN5bmNocm9ub3VzbHkgc2lnbnMgaW4gdXNpbmcgYW4gZW1haWwgYW5kIHBhc3N3b3JkLlxuICpcbiAqIEByZW1hcmtzXG4gKiBGYWlscyB3aXRoIGFuIGVycm9yIGlmIHRoZSBlbWFpbCBhZGRyZXNzIGFuZCBwYXNzd29yZCBkbyBub3QgbWF0Y2guIFdoZW5cbiAqIHtAbGluayBodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWRlbnRpdHktcGxhdGZvcm0vZG9jcy9hZG1pbi9lbWFpbC1lbnVtZXJhdGlvbi1wcm90ZWN0aW9uIHwgRW1haWwgRW51bWVyYXRpb24gUHJvdGVjdGlvbn1cbiAqIGlzIGVuYWJsZWQsIHRoaXMgbWV0aG9kIGZhaWxzIHdpdGggXCJhdXRoL2ludmFsaWQtY3JlZGVudGlhbFwiIGluIGNhc2Ugb2YgYW4gaW52YWxpZFxuICogZW1haWwvcGFzc3dvcmQuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBvbiB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogTm90ZTogVGhlIHVzZXIncyBwYXNzd29yZCBpcyBOT1QgdGhlIHBhc3N3b3JkIHVzZWQgdG8gYWNjZXNzIHRoZSB1c2VyJ3MgZW1haWwgYWNjb3VudC4gVGhlXG4gKiBlbWFpbCBhZGRyZXNzIHNlcnZlcyBhcyBhIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgdXNlciwgYW5kIHRoZSBwYXNzd29yZCBpcyB1c2VkIHRvIGFjY2Vzc1xuICogdGhlIHVzZXIncyBhY2NvdW50IGluIHlvdXIgRmlyZWJhc2UgcHJvamVjdC4gU2VlIGFsc286IHtAbGluayBjcmVhdGVVc2VyV2l0aEVtYWlsQW5kUGFzc3dvcmR9LlxuICpcbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gZW1haWwgLSBUaGUgdXNlcnMgZW1haWwgYWRkcmVzcy5cbiAqIEBwYXJhbSBwYXNzd29yZCAtIFRoZSB1c2VycyBwYXNzd29yZC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduSW5XaXRoRW1haWxBbmRQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZyxcbiAgcGFzc3dvcmQ6IHN0cmluZ1xuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAoYXV0aC5hcHApKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IoYXV0aClcbiAgICApO1xuICB9XG4gIHJldHVybiBzaWduSW5XaXRoQ3JlZGVudGlhbChcbiAgICBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksXG4gICAgRW1haWxBdXRoUHJvdmlkZXIuY3JlZGVudGlhbChlbWFpbCwgcGFzc3dvcmQpXG4gICkuY2F0Y2goYXN5bmMgZXJyb3IgPT4ge1xuICAgIGlmIChcbiAgICAgIGVycm9yLmNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5QQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UU31gXG4gICAgKSB7XG4gICAgICB2b2lkIHJlY2FjaGVQYXNzd29yZFBvbGljeShhdXRoKTtcbiAgICB9XG5cbiAgICB0aHJvdyBlcnJvcjtcbiAgfSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgQWN0aW9uQ29kZU9wZXJhdGlvbixcbiAgQWN0aW9uQ29kZVNldHRpbmdzLFxuICBBdXRoLFxuICBVc2VyQ3JlZGVudGlhbFxufSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQgKiBhcyBhcGkgZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBBY3Rpb25Db2RlVVJMIH0gZnJvbSAnLi4vYWN0aW9uX2NvZGVfdXJsJztcbmltcG9ydCB7IEVtYWlsQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi4vcHJvdmlkZXJzL2VtYWlsJztcbmltcG9ydCB7IF9nZXRDdXJyZW50VXJsIH0gZnJvbSAnLi4vdXRpbC9sb2NhdGlvbic7XG5pbXBvcnQgeyBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0IH0gZnJvbSAnLi9hY3Rpb25fY29kZV9zZXR0aW5ncyc7XG5pbXBvcnQgeyBzaWduSW5XaXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vY3JlZGVudGlhbCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBfY2FzdEF1dGggfSBmcm9tICcuLi9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgeyBoYW5kbGVSZWNhcHRjaGFGbG93IH0gZnJvbSAnLi4vLi4vcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXInO1xuaW1wb3J0IHtcbiAgUmVjYXB0Y2hhQWN0aW9uTmFtZSxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyXG59IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQgeyBfaXNGaXJlYmFzZVNlcnZlckFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvYXNzZXJ0JztcblxuLyoqXG4gKiBTZW5kcyBhIHNpZ24taW4gZW1haWwgbGluayB0byB0aGUgdXNlciB3aXRoIHRoZSBzcGVjaWZpZWQgZW1haWwuXG4gKlxuICogQHJlbWFya3NcbiAqIFRoZSBzaWduLWluIG9wZXJhdGlvbiBoYXMgdG8gYWx3YXlzIGJlIGNvbXBsZXRlZCBpbiB0aGUgYXBwIHVubGlrZSBvdGhlciBvdXQgb2YgYmFuZCBlbWFpbFxuICogYWN0aW9ucyAocGFzc3dvcmQgcmVzZXQgYW5kIGVtYWlsIHZlcmlmaWNhdGlvbnMpLiBUaGlzIGlzIGJlY2F1c2UsIGF0IHRoZSBlbmQgb2YgdGhlIGZsb3csXG4gKiB0aGUgdXNlciBpcyBleHBlY3RlZCB0byBiZSBzaWduZWQgaW4gYW5kIHRoZWlyIEF1dGggc3RhdGUgcGVyc2lzdGVkIHdpdGhpbiB0aGUgYXBwLlxuICpcbiAqIFRvIGNvbXBsZXRlIHNpZ24gaW4gd2l0aCB0aGUgZW1haWwgbGluaywgY2FsbCB7QGxpbmsgc2lnbkluV2l0aEVtYWlsTGlua30gd2l0aCB0aGUgZW1haWxcbiAqIGFkZHJlc3MgYW5kIHRoZSBlbWFpbCBsaW5rIHN1cHBsaWVkIGluIHRoZSBlbWFpbCBzZW50IHRvIHRoZSB1c2VyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHNlbmRTaWduSW5MaW5rVG9FbWFpbChhdXRoLCAndXNlckBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gZW1haWxMaW5rIGZyb20gdGhlIHVzZXIuXG4gKiBpZihpc1NpZ25JbldpdGhFbWFpbExpbmsoYXV0aCwgZW1haWxMaW5rKSkge1xuICogICBhd2FpdCBzaWduSW5XaXRoRW1haWxMaW5rKGF1dGgsICd1c2VyQGV4YW1wbGUuY29tJywgZW1haWxMaW5rKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBhdXRoSW50ZXJuYWwgLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVtYWlsIC0gVGhlIHVzZXIncyBlbWFpbCBhZGRyZXNzLlxuICogQHBhcmFtIGFjdGlvbkNvZGVTZXR0aW5ncyAtIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVNldHRpbmdzfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kU2lnbkluTGlua1RvRW1haWwoXG4gIGF1dGg6IEF1dGgsXG4gIGVtYWlsOiBzdHJpbmcsXG4gIGFjdGlvbkNvZGVTZXR0aW5nczogQWN0aW9uQ29kZVNldHRpbmdzXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICBjb25zdCByZXF1ZXN0OiBhcGkuRW1haWxTaWduSW5SZXF1ZXN0ID0ge1xuICAgIHJlcXVlc3RUeXBlOiBBY3Rpb25Db2RlT3BlcmF0aW9uLkVNQUlMX1NJR05JTixcbiAgICBlbWFpbCxcbiAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICB9O1xuICBmdW5jdGlvbiBzZXRBY3Rpb25Db2RlU2V0dGluZ3MoXG4gICAgcmVxdWVzdDogYXBpLkVtYWlsU2lnbkluUmVxdWVzdCxcbiAgICBhY3Rpb25Db2RlU2V0dGluZ3M6IEFjdGlvbkNvZGVTZXR0aW5nc1xuICApOiB2b2lkIHtcbiAgICBfYXNzZXJ0KFxuICAgICAgYWN0aW9uQ29kZVNldHRpbmdzLmhhbmRsZUNvZGVJbkFwcCxcbiAgICAgIGF1dGhJbnRlcm5hbCxcbiAgICAgIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JcbiAgICApO1xuICAgIGlmIChhY3Rpb25Db2RlU2V0dGluZ3MpIHtcbiAgICAgIF9zZXRBY3Rpb25Db2RlU2V0dGluZ3NPblJlcXVlc3QoXG4gICAgICAgIGF1dGhJbnRlcm5hbCxcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgYWN0aW9uQ29kZVNldHRpbmdzXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBzZXRBY3Rpb25Db2RlU2V0dGluZ3MocmVxdWVzdCwgYWN0aW9uQ29kZVNldHRpbmdzKTtcbiAgYXdhaXQgaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgcmVxdWVzdCxcbiAgICBSZWNhcHRjaGFBY3Rpb25OYW1lLkdFVF9PT0JfQ09ERSxcbiAgICBhcGkuc2VuZFNpZ25JbkxpbmtUb0VtYWlsLFxuICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICApO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBpbmNvbWluZyBsaW5rIGlzIGEgc2lnbi1pbiB3aXRoIGVtYWlsIGxpbmsgc3VpdGFibGUgZm9yIHtAbGluayBzaWduSW5XaXRoRW1haWxMaW5rfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gZW1haWxMaW5rIC0gVGhlIGxpbmsgc2VudCB0byB0aGUgdXNlcidzIGVtYWlsIGFkZHJlc3MuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTaWduSW5XaXRoRW1haWxMaW5rKGF1dGg6IEF1dGgsIGVtYWlsTGluazogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGFjdGlvbkNvZGVVcmwgPSBBY3Rpb25Db2RlVVJMLnBhcnNlTGluayhlbWFpbExpbmspO1xuICByZXR1cm4gYWN0aW9uQ29kZVVybD8ub3BlcmF0aW9uID09PSBBY3Rpb25Db2RlT3BlcmF0aW9uLkVNQUlMX1NJR05JTjtcbn1cblxuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzaWducyBpbiB1c2luZyBhbiBlbWFpbCBhbmQgc2lnbi1pbiBlbWFpbCBsaW5rLlxuICpcbiAqIEByZW1hcmtzXG4gKiBJZiBubyBsaW5rIGlzIHBhc3NlZCwgdGhlIGxpbmsgaXMgaW5mZXJyZWQgZnJvbSB0aGUgY3VycmVudCBVUkwuXG4gKlxuICogRmFpbHMgd2l0aCBhbiBlcnJvciBpZiB0aGUgZW1haWwgYWRkcmVzcyBpcyBpbnZhbGlkIG9yIE9UUCBpbiBlbWFpbCBsaW5rIGV4cGlyZXMuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogTm90ZTogQ29uZmlybSB0aGUgbGluayBpcyBhIHNpZ24taW4gZW1haWwgbGluayBiZWZvcmUgY2FsbGluZyB0aGlzIG1ldGhvZCBmaXJlYmFzZS5hdXRoLkF1dGguaXNTaWduSW5XaXRoRW1haWxMaW5rLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHNlbmRTaWduSW5MaW5rVG9FbWFpbChhdXRoLCAndXNlckBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gZW1haWxMaW5rIGZyb20gdGhlIHVzZXIuXG4gKiBpZihpc1NpZ25JbldpdGhFbWFpbExpbmsoYXV0aCwgZW1haWxMaW5rKSkge1xuICogICBhd2FpdCBzaWduSW5XaXRoRW1haWxMaW5rKGF1dGgsICd1c2VyQGV4YW1wbGUuY29tJywgZW1haWxMaW5rKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gZW1haWwgLSBUaGUgdXNlcidzIGVtYWlsIGFkZHJlc3MuXG4gKiBAcGFyYW0gZW1haWxMaW5rIC0gVGhlIGxpbmsgc2VudCB0byB0aGUgdXNlcidzIGVtYWlsIGFkZHJlc3MuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aEVtYWlsTGluayhcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZyxcbiAgZW1haWxMaW5rPzogc3RyaW5nXG4pOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcChhdXRoLmFwcCkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcihhdXRoKVxuICAgICk7XG4gIH1cbiAgY29uc3QgYXV0aE1vZHVsYXIgPSBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCk7XG4gIGNvbnN0IGNyZWRlbnRpYWwgPSBFbWFpbEF1dGhQcm92aWRlci5jcmVkZW50aWFsV2l0aExpbmsoXG4gICAgZW1haWwsXG4gICAgZW1haWxMaW5rIHx8IF9nZXRDdXJyZW50VXJsKClcbiAgKTtcbiAgLy8gQ2hlY2sgaWYgdGhlIHRlbmFudCBJRCBpbiB0aGUgZW1haWwgbGluayBtYXRjaGVzIHRoZSB0ZW5hbnQgSUQgb24gQXV0aFxuICAvLyBpbnN0YW5jZS5cbiAgX2Fzc2VydChcbiAgICBjcmVkZW50aWFsLl90ZW5hbnRJZCA9PT0gKGF1dGhNb2R1bGFyLnRlbmFudElkIHx8IG51bGwpLFxuICAgIGF1dGhNb2R1bGFyLFxuICAgIEF1dGhFcnJvckNvZGUuVEVOQU5UX0lEX01JU01BVENIXG4gICk7XG4gIHJldHVybiBzaWduSW5XaXRoQ3JlZGVudGlhbChhdXRoTW9kdWxhciwgY3JlZGVudGlhbCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeSxcbiAgX3BlcmZvcm1BcGlSZXF1ZXN0XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEF1dGggfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUF1dGhVcmlSZXF1ZXN0IHtcbiAgaWRlbnRpZmllcjogc3RyaW5nO1xuICBjb250aW51ZVVyaTogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBdXRoVXJpUmVzcG9uc2Uge1xuICBzaWduaW5NZXRob2RzOiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUF1dGhVcmkoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IENyZWF0ZUF1dGhVcmlSZXF1ZXN0XG4pOiBQcm9taXNlPENyZWF0ZUF1dGhVcmlSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PENyZWF0ZUF1dGhVcmlSZXF1ZXN0LCBDcmVhdGVBdXRoVXJpUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LkNSRUFURV9BVVRIX1VSSSxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBBY3Rpb25Db2RlT3BlcmF0aW9uLFxuICBBY3Rpb25Db2RlU2V0dGluZ3MsXG4gIEF1dGgsXG4gIFVzZXJcbn0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlQXV0aFVyaSxcbiAgQ3JlYXRlQXV0aFVyaVJlcXVlc3Rcbn0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2NyZWF0ZV9hdXRoX3VyaSc7XG5pbXBvcnQgKiBhcyBhcGkgZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IF9nZXRDdXJyZW50VXJsLCBfaXNIdHRwT3JIdHRwcyB9IGZyb20gJy4uL3V0aWwvbG9jYXRpb24nO1xuaW1wb3J0IHsgX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdCB9IGZyb20gJy4vYWN0aW9uX2NvZGVfc2V0dGluZ3MnO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vKipcbiAqIEdldHMgdGhlIGxpc3Qgb2YgcG9zc2libGUgc2lnbiBpbiBtZXRob2RzIGZvciB0aGUgZ2l2ZW4gZW1haWwgYWRkcmVzcy4gVGhpcyBtZXRob2QgcmV0dXJucyBhblxuICogZW1wdHkgbGlzdCB3aGVuXG4gKiB7QGxpbmsgaHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL2lkZW50aXR5LXBsYXRmb3JtL2RvY3MvYWRtaW4vZW1haWwtZW51bWVyYXRpb24tcHJvdGVjdGlvbiB8IEVtYWlsIEVudW1lcmF0aW9uIFByb3RlY3Rpb259XG4gKiBpcyBlbmFibGVkLCBpcnJlc3BlY3RpdmUgb2YgdGhlIG51bWJlciBvZiBhdXRoZW50aWNhdGlvbiBtZXRob2RzIGF2YWlsYWJsZSBmb3IgdGhlIGdpdmVuIGVtYWlsLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGlzIHVzZWZ1bCB0byBkaWZmZXJlbnRpYXRlIG1ldGhvZHMgb2Ygc2lnbi1pbiBmb3IgdGhlIHNhbWUgcHJvdmlkZXIsIGVnLlxuICoge0BsaW5rIEVtYWlsQXV0aFByb3ZpZGVyfSB3aGljaCBoYXMgMiBtZXRob2RzIG9mIHNpZ24taW4sXG4gKiB7QGxpbmsgU2lnbkluTWV0aG9kfS5FTUFJTF9QQVNTV09SRCBhbmRcbiAqIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX0xJTksuXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVtYWlsIC0gVGhlIHVzZXIncyBlbWFpbCBhZGRyZXNzLlxuICpcbiAqIERlcHJlY2F0ZWQuIE1pZ3JhdGluZyBvZmYgb2YgdGhpcyBtZXRob2QgaXMgcmVjb21tZW5kZWQgYXMgYSBzZWN1cml0eSBiZXN0LXByYWN0aWNlLlxuICogTGVhcm4gbW9yZSBpbiB0aGUgSWRlbnRpdHkgUGxhdGZvcm0gZG9jdW1lbnRhdGlvbiBmb3JcbiAqIHtAbGluayBodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWRlbnRpdHktcGxhdGZvcm0vZG9jcy9hZG1pbi9lbWFpbC1lbnVtZXJhdGlvbi1wcm90ZWN0aW9uIHwgRW1haWwgRW51bWVyYXRpb24gUHJvdGVjdGlvbn0uXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAvLyBjcmVhdGVBdXRoVXJpIHJldHVybnMgYW4gZXJyb3IgaWYgY29udGludWUgVVJJIGlzIG5vdCBodHRwIG9yIGh0dHBzLlxuICAvLyBGb3IgZW52aXJvbm1lbnRzIGxpa2UgQ29yZG92YSwgQ2hyb21lIGV4dGVuc2lvbnMsIG5hdGl2ZSBmcmFtZXdvcmtzLCBmaWxlXG4gIC8vIHN5c3RlbXMsIGV0YywgdXNlIGh0dHA6Ly9sb2NhbGhvc3QgYXMgY29udGludWUgVVJMLlxuICBjb25zdCBjb250aW51ZVVyaSA9IF9pc0h0dHBPckh0dHBzKCkgPyBfZ2V0Q3VycmVudFVybCgpIDogJ2h0dHA6Ly9sb2NhbGhvc3QnO1xuICBjb25zdCByZXF1ZXN0OiBDcmVhdGVBdXRoVXJpUmVxdWVzdCA9IHtcbiAgICBpZGVudGlmaWVyOiBlbWFpbCxcbiAgICBjb250aW51ZVVyaVxuICB9O1xuXG4gIGNvbnN0IHsgc2lnbmluTWV0aG9kcyB9ID0gYXdhaXQgY3JlYXRlQXV0aFVyaShcbiAgICBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksXG4gICAgcmVxdWVzdFxuICApO1xuXG4gIHJldHVybiBzaWduaW5NZXRob2RzIHx8IFtdO1xufVxuXG4vKipcbiAqIFNlbmRzIGEgdmVyaWZpY2F0aW9uIGVtYWlsIHRvIGEgdXNlci5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhlIHZlcmlmaWNhdGlvbiBwcm9jZXNzIGlzIGNvbXBsZXRlZCBieSBjYWxsaW5nIHtAbGluayBhcHBseUFjdGlvbkNvZGV9LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHNlbmRFbWFpbFZlcmlmaWNhdGlvbih1c2VyLCBhY3Rpb25Db2RlU2V0dGluZ3MpO1xuICogLy8gT2J0YWluIGNvZGUgZnJvbSB0aGUgdXNlci5cbiAqIGF3YWl0IGFwcGx5QWN0aW9uQ29kZShhdXRoLCBjb2RlKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gYWN0aW9uQ29kZVNldHRpbmdzIC0gVGhlIHtAbGluayBBY3Rpb25Db2RlU2V0dGluZ3N9LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmRFbWFpbFZlcmlmaWNhdGlvbihcbiAgdXNlcjogVXNlcixcbiAgYWN0aW9uQ29kZVNldHRpbmdzPzogQWN0aW9uQ29kZVNldHRpbmdzIHwgbnVsbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbCA9IGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWw7XG4gIGNvbnN0IGlkVG9rZW4gPSBhd2FpdCB1c2VyLmdldElkVG9rZW4oKTtcbiAgY29uc3QgcmVxdWVzdDogYXBpLlZlcmlmeUVtYWlsUmVxdWVzdCA9IHtcbiAgICByZXF1ZXN0VHlwZTogQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfRU1BSUwsXG4gICAgaWRUb2tlblxuICB9O1xuICBpZiAoYWN0aW9uQ29kZVNldHRpbmdzKSB7XG4gICAgX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdChcbiAgICAgIHVzZXJJbnRlcm5hbC5hdXRoLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGFjdGlvbkNvZGVTZXR0aW5nc1xuICAgICk7XG4gIH1cblxuICBjb25zdCB7IGVtYWlsIH0gPSBhd2FpdCBhcGkuc2VuZEVtYWlsVmVyaWZpY2F0aW9uKHVzZXJJbnRlcm5hbC5hdXRoLCByZXF1ZXN0KTtcblxuICBpZiAoZW1haWwgIT09IHVzZXIuZW1haWwpIHtcbiAgICBhd2FpdCB1c2VyLnJlbG9hZCgpO1xuICB9XG59XG5cbi8qKlxuICogU2VuZHMgYSB2ZXJpZmljYXRpb24gZW1haWwgdG8gYSBuZXcgZW1haWwgYWRkcmVzcy5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhlIHVzZXIncyBlbWFpbCB3aWxsIGJlIHVwZGF0ZWQgdG8gdGhlIG5ldyBvbmUgYWZ0ZXIgYmVpbmcgdmVyaWZpZWQuXG4gKlxuICogSWYgeW91IGhhdmUgYSBjdXN0b20gZW1haWwgYWN0aW9uIGhhbmRsZXIsIHlvdSBjYW4gY29tcGxldGUgdGhlIHZlcmlmaWNhdGlvbiBwcm9jZXNzIGJ5IGNhbGxpbmdcbiAqIHtAbGluayBhcHBseUFjdGlvbkNvZGV9LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHZlcmlmeUJlZm9yZVVwZGF0ZUVtYWlsKHVzZXIsICduZXdlbWFpbEBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gY29kZSBmcm9tIHRoZSB1c2VyLlxuICogYXdhaXQgYXBwbHlBY3Rpb25Db2RlKGF1dGgsIGNvZGUpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBuZXdFbWFpbCAtIFRoZSBuZXcgZW1haWwgYWRkcmVzcyB0byBiZSB2ZXJpZmllZCBiZWZvcmUgdXBkYXRlLlxuICogQHBhcmFtIGFjdGlvbkNvZGVTZXR0aW5ncyAtIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVNldHRpbmdzfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlCZWZvcmVVcGRhdGVFbWFpbChcbiAgdXNlcjogVXNlcixcbiAgbmV3RW1haWw6IHN0cmluZyxcbiAgYWN0aW9uQ29kZVNldHRpbmdzPzogQWN0aW9uQ29kZVNldHRpbmdzIHwgbnVsbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbCA9IGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWw7XG4gIGNvbnN0IGlkVG9rZW4gPSBhd2FpdCB1c2VyLmdldElkVG9rZW4oKTtcbiAgY29uc3QgcmVxdWVzdDogYXBpLlZlcmlmeUFuZENoYW5nZUVtYWlsUmVxdWVzdCA9IHtcbiAgICByZXF1ZXN0VHlwZTogQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfQU5EX0NIQU5HRV9FTUFJTCxcbiAgICBpZFRva2VuLFxuICAgIG5ld0VtYWlsXG4gIH07XG4gIGlmIChhY3Rpb25Db2RlU2V0dGluZ3MpIHtcbiAgICBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0KFxuICAgICAgdXNlckludGVybmFsLmF1dGgsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYWN0aW9uQ29kZVNldHRpbmdzXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHsgZW1haWwgfSA9IGF3YWl0IGFwaS52ZXJpZnlBbmRDaGFuZ2VFbWFpbCh1c2VySW50ZXJuYWwuYXV0aCwgcmVxdWVzdCk7XG5cbiAgaWYgKGVtYWlsICE9PSB1c2VyLmVtYWlsKSB7XG4gICAgLy8gSWYgdGhlIGxvY2FsIGNvcHkgb2YgdGhlIGVtYWlsIG9uIHVzZXIgaXMgb3V0ZGF0ZWQsIHJlbG9hZCB0aGVcbiAgICAvLyB1c2VyLlxuICAgIGF3YWl0IHVzZXIucmVsb2FkKCk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBFbmRwb2ludCwgSHR0cE1ldGhvZCwgX3BlcmZvcm1BcGlSZXF1ZXN0IH0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlUHJvZmlsZVJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbDtcbiAgcGhvdG9Vcmw/OiBzdHJpbmcgfCBudWxsO1xuICByZXR1cm5TZWN1cmVUb2tlbjogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBVcGRhdGVQcm9maWxlUmVzcG9uc2UgZXh0ZW5kcyBJZFRva2VuUmVzcG9uc2Uge1xuICBkaXNwbGF5TmFtZT86IHN0cmluZyB8IG51bGw7XG4gIHBob3RvVXJsPzogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVByb2ZpbGUoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFVwZGF0ZVByb2ZpbGVSZXF1ZXN0XG4pOiBQcm9taXNlPFVwZGF0ZVByb2ZpbGVSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFVwZGF0ZVByb2ZpbGVSZXF1ZXN0LCBVcGRhdGVQcm9maWxlUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNFVF9BQ0NPVU5UX0lORk8sXG4gICAgcmVxdWVzdFxuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQge1xuICB1cGRhdGVFbWFpbFBhc3N3b3JkIGFzIGFwaVVwZGF0ZUVtYWlsUGFzc3dvcmQsXG4gIFVwZGF0ZUVtYWlsUGFzc3dvcmRSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvZW1haWxfYW5kX3Bhc3N3b3JkJztcbmltcG9ydCB7IHVwZGF0ZVByb2ZpbGUgYXMgYXBpVXBkYXRlUHJvZmlsZSB9IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvcHJvZmlsZSc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgUHJvdmlkZXJJZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvciB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIFVwZGF0ZXMgYSB1c2VyJ3MgcHJvZmlsZSBkYXRhLlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gcHJvZmlsZSAtIFRoZSBwcm9maWxlJ3MgYGRpc3BsYXlOYW1lYCBhbmQgYHBob3RvVVJMYCB0byB1cGRhdGUuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlUHJvZmlsZShcbiAgdXNlcjogVXNlcixcbiAge1xuICAgIGRpc3BsYXlOYW1lLFxuICAgIHBob3RvVVJMOiBwaG90b1VybFxuICB9OiB7IGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbDsgcGhvdG9VUkw/OiBzdHJpbmcgfCBudWxsIH1cbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoZGlzcGxheU5hbWUgPT09IHVuZGVmaW5lZCAmJiBwaG90b1VybCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgdXNlckludGVybmFsID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbDtcbiAgY29uc3QgaWRUb2tlbiA9IGF3YWl0IHVzZXJJbnRlcm5hbC5nZXRJZFRva2VuKCk7XG4gIGNvbnN0IHByb2ZpbGVSZXF1ZXN0ID0ge1xuICAgIGlkVG9rZW4sXG4gICAgZGlzcGxheU5hbWUsXG4gICAgcGhvdG9VcmwsXG4gICAgcmV0dXJuU2VjdXJlVG9rZW46IHRydWVcbiAgfTtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBfbG9nb3V0SWZJbnZhbGlkYXRlZChcbiAgICB1c2VySW50ZXJuYWwsXG4gICAgYXBpVXBkYXRlUHJvZmlsZSh1c2VySW50ZXJuYWwuYXV0aCwgcHJvZmlsZVJlcXVlc3QpXG4gICk7XG5cbiAgdXNlckludGVybmFsLmRpc3BsYXlOYW1lID0gcmVzcG9uc2UuZGlzcGxheU5hbWUgfHwgbnVsbDtcbiAgdXNlckludGVybmFsLnBob3RvVVJMID0gcmVzcG9uc2UucGhvdG9VcmwgfHwgbnVsbDtcblxuICAvLyBVcGRhdGUgdGhlIHBhc3N3b3JkIHByb3ZpZGVyIGFzIHdlbGxcbiAgY29uc3QgcGFzc3dvcmRQcm92aWRlciA9IHVzZXJJbnRlcm5hbC5wcm92aWRlckRhdGEuZmluZChcbiAgICAoeyBwcm92aWRlcklkIH0pID0+IHByb3ZpZGVySWQgPT09IFByb3ZpZGVySWQuUEFTU1dPUkRcbiAgKTtcbiAgaWYgKHBhc3N3b3JkUHJvdmlkZXIpIHtcbiAgICBwYXNzd29yZFByb3ZpZGVyLmRpc3BsYXlOYW1lID0gdXNlckludGVybmFsLmRpc3BsYXlOYW1lO1xuICAgIHBhc3N3b3JkUHJvdmlkZXIucGhvdG9VUkwgPSB1c2VySW50ZXJuYWwucGhvdG9VUkw7XG4gIH1cblxuICBhd2FpdCB1c2VySW50ZXJuYWwuX3VwZGF0ZVRva2Vuc0lmTmVjZXNzYXJ5KHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBVcGRhdGVzIHRoZSB1c2VyJ3MgZW1haWwgYWRkcmVzcy5cbiAqXG4gKiBAcmVtYXJrc1xuICogQW4gZW1haWwgd2lsbCBiZSBzZW50IHRvIHRoZSBvcmlnaW5hbCBlbWFpbCBhZGRyZXNzIChpZiBpdCB3YXMgc2V0KSB0aGF0IGFsbG93cyB0byByZXZva2UgdGhlXG4gKiBlbWFpbCBhZGRyZXNzIGNoYW5nZSwgaW4gb3JkZXIgdG8gcHJvdGVjdCB0aGVtIGZyb20gYWNjb3VudCBoaWphY2tpbmcuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBvbiBhbnkge0BsaW5rIFVzZXJ9IHNpZ25lZCBpbiBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzXG4gKiBjcmVhdGVkIHdpdGggYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogSW1wb3J0YW50OiB0aGlzIGlzIGEgc2VjdXJpdHkgc2Vuc2l0aXZlIG9wZXJhdGlvbiB0aGF0IHJlcXVpcmVzIHRoZSB1c2VyIHRvIGhhdmUgcmVjZW50bHkgc2lnbmVkXG4gKiBpbi4gSWYgdGhpcyByZXF1aXJlbWVudCBpc24ndCBtZXQsIGFzayB0aGUgdXNlciB0byBhdXRoZW50aWNhdGUgYWdhaW4gYW5kIHRoZW4gY2FsbFxuICoge0BsaW5rIHJlYXV0aGVudGljYXRlV2l0aENyZWRlbnRpYWx9LlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gbmV3RW1haWwgLSBUaGUgbmV3IGVtYWlsIGFkZHJlc3MuXG4gKlxuICogVGhyb3dzIFwiYXV0aC9vcGVyYXRpb24tbm90LWFsbG93ZWRcIiBlcnJvciB3aGVuXG4gKiB7QGxpbmsgaHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL2lkZW50aXR5LXBsYXRmb3JtL2RvY3MvYWRtaW4vZW1haWwtZW51bWVyYXRpb24tcHJvdGVjdGlvbiB8IEVtYWlsIEVudW1lcmF0aW9uIFByb3RlY3Rpb259XG4gKiBpcyBlbmFibGVkLlxuICogRGVwcmVjYXRlZCAtIFVzZSB7QGxpbmsgdmVyaWZ5QmVmb3JlVXBkYXRlRW1haWx9IGluc3RlYWQuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlRW1haWwodXNlcjogVXNlciwgbmV3RW1haWw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB1c2VySW50ZXJuYWwgPSBnZXRNb2R1bGFySW5zdGFuY2UodXNlcikgYXMgVXNlckludGVybmFsO1xuICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAodXNlckludGVybmFsLmF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKHVzZXJJbnRlcm5hbC5hdXRoKVxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHVwZGF0ZUVtYWlsT3JQYXNzd29yZCh1c2VySW50ZXJuYWwsIG5ld0VtYWlsLCBudWxsKTtcbn1cblxuLyoqXG4gKiBVcGRhdGVzIHRoZSB1c2VyJ3MgcGFzc3dvcmQuXG4gKlxuICogQHJlbWFya3NcbiAqIEltcG9ydGFudDogdGhpcyBpcyBhIHNlY3VyaXR5IHNlbnNpdGl2ZSBvcGVyYXRpb24gdGhhdCByZXF1aXJlcyB0aGUgdXNlciB0byBoYXZlIHJlY2VudGx5IHNpZ25lZFxuICogaW4uIElmIHRoaXMgcmVxdWlyZW1lbnQgaXNuJ3QgbWV0LCBhc2sgdGhlIHVzZXIgdG8gYXV0aGVudGljYXRlIGFnYWluIGFuZCB0aGVuIGNhbGxcbiAqIHtAbGluayByZWF1dGhlbnRpY2F0ZVdpdGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAcGFyYW0gdXNlciAtIFRoZSB1c2VyLlxuICogQHBhcmFtIG5ld1Bhc3N3b3JkIC0gVGhlIG5ldyBwYXNzd29yZC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVQYXNzd29yZCh1c2VyOiBVc2VyLCBuZXdQYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiB1cGRhdGVFbWFpbE9yUGFzc3dvcmQoXG4gICAgZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbCxcbiAgICBudWxsLFxuICAgIG5ld1Bhc3N3b3JkXG4gICk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUVtYWlsT3JQYXNzd29yZChcbiAgdXNlcjogVXNlckludGVybmFsLFxuICBlbWFpbDogc3RyaW5nIHwgbnVsbCxcbiAgcGFzc3dvcmQ6IHN0cmluZyB8IG51bGxcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IGF1dGggfSA9IHVzZXI7XG4gIGNvbnN0IGlkVG9rZW4gPSBhd2FpdCB1c2VyLmdldElkVG9rZW4oKTtcbiAgY29uc3QgcmVxdWVzdDogVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3QgPSB7XG4gICAgaWRUb2tlbixcbiAgICByZXR1cm5TZWN1cmVUb2tlbjogdHJ1ZVxuICB9O1xuXG4gIGlmIChlbWFpbCkge1xuICAgIHJlcXVlc3QuZW1haWwgPSBlbWFpbDtcbiAgfVxuXG4gIGlmIChwYXNzd29yZCkge1xuICAgIHJlcXVlc3QucGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQoXG4gICAgdXNlcixcbiAgICBhcGlVcGRhdGVFbWFpbFBhc3N3b3JkKGF1dGgsIHJlcXVlc3QpXG4gICk7XG4gIGF3YWl0IHVzZXIuX3VwZGF0ZVRva2Vuc0lmTmVjZXNzYXJ5KHJlc3BvbnNlLCAvKiByZWxvYWQgKi8gdHJ1ZSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQWRkaXRpb25hbFVzZXJJbmZvLCBVc2VyQ3JlZGVudGlhbCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UsIElkVG9rZW5SZXNwb25zZUtpbmQgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBfcGFyc2VUb2tlbiB9IGZyb20gJy4vaWRfdG9rZW5fcmVzdWx0JztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IFByb3ZpZGVySWQgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5cbi8qKlxuICogUGFyc2UgdGhlIGBBZGRpdGlvbmFsVXNlckluZm9gIGZyb20gdGhlIElEIHRva2VuIHJlc3BvbnNlLlxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9mcm9tSWRUb2tlblJlc3BvbnNlKFxuICBpZFRva2VuUmVzcG9uc2U/OiBJZFRva2VuUmVzcG9uc2Vcbik6IEFkZGl0aW9uYWxVc2VySW5mbyB8IG51bGwge1xuICBpZiAoIWlkVG9rZW5SZXNwb25zZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHsgcHJvdmlkZXJJZCB9ID0gaWRUb2tlblJlc3BvbnNlO1xuICBjb25zdCBwcm9maWxlID0gaWRUb2tlblJlc3BvbnNlLnJhd1VzZXJJbmZvXG4gICAgPyBKU09OLnBhcnNlKGlkVG9rZW5SZXNwb25zZS5yYXdVc2VySW5mbylcbiAgICA6IHt9O1xuICBjb25zdCBpc05ld1VzZXIgPVxuICAgIGlkVG9rZW5SZXNwb25zZS5pc05ld1VzZXIgfHxcbiAgICBpZFRva2VuUmVzcG9uc2Uua2luZCA9PT0gSWRUb2tlblJlc3BvbnNlS2luZC5TaWdudXBOZXdVc2VyO1xuICBpZiAoIXByb3ZpZGVySWQgJiYgaWRUb2tlblJlc3BvbnNlPy5pZFRva2VuKSB7XG4gICAgY29uc3Qgc2lnbkluUHJvdmlkZXIgPSBfcGFyc2VUb2tlbihpZFRva2VuUmVzcG9uc2UuaWRUb2tlbik/LmZpcmViYXNlPy5bXG4gICAgICAnc2lnbl9pbl9wcm92aWRlcidcbiAgICBdO1xuICAgIGlmIChzaWduSW5Qcm92aWRlcikge1xuICAgICAgY29uc3QgZmlsdGVyZWRQcm92aWRlcklkID1cbiAgICAgICAgc2lnbkluUHJvdmlkZXIgIT09IFByb3ZpZGVySWQuQU5PTllNT1VTICYmXG4gICAgICAgIHNpZ25JblByb3ZpZGVyICE9PSBQcm92aWRlcklkLkNVU1RPTVxuICAgICAgICAgID8gKHNpZ25JblByb3ZpZGVyIGFzIFByb3ZpZGVySWQpXG4gICAgICAgICAgOiBudWxsO1xuICAgICAgLy8gVXNlcyBnZW5lcmljIGNsYXNzIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgbGVnYWN5IFNESy5cbiAgICAgIHJldHVybiBuZXcgR2VuZXJpY0FkZGl0aW9uYWxVc2VySW5mbyhpc05ld1VzZXIsIGZpbHRlcmVkUHJvdmlkZXJJZCk7XG4gICAgfVxuICB9XG4gIGlmICghcHJvdmlkZXJJZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHN3aXRjaCAocHJvdmlkZXJJZCkge1xuICAgIGNhc2UgUHJvdmlkZXJJZC5GQUNFQk9PSzpcbiAgICAgIHJldHVybiBuZXcgRmFjZWJvb2tBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm9maWxlKTtcbiAgICBjYXNlIFByb3ZpZGVySWQuR0lUSFVCOlxuICAgICAgcmV0dXJuIG5ldyBHaXRodWJBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm9maWxlKTtcbiAgICBjYXNlIFByb3ZpZGVySWQuR09PR0xFOlxuICAgICAgcmV0dXJuIG5ldyBHb29nbGVBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm9maWxlKTtcbiAgICBjYXNlIFByb3ZpZGVySWQuVFdJVFRFUjpcbiAgICAgIHJldHVybiBuZXcgVHdpdHRlckFkZGl0aW9uYWxVc2VySW5mbyhcbiAgICAgICAgaXNOZXdVc2VyLFxuICAgICAgICBwcm9maWxlLFxuICAgICAgICBpZFRva2VuUmVzcG9uc2Uuc2NyZWVuTmFtZSB8fCBudWxsXG4gICAgICApO1xuICAgIGNhc2UgUHJvdmlkZXJJZC5DVVNUT006XG4gICAgY2FzZSBQcm92aWRlcklkLkFOT05ZTU9VUzpcbiAgICAgIHJldHVybiBuZXcgR2VuZXJpY0FkZGl0aW9uYWxVc2VySW5mbyhpc05ld1VzZXIsIG51bGwpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IEdlbmVyaWNBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm92aWRlcklkLCBwcm9maWxlKTtcbiAgfVxufVxuXG5jbGFzcyBHZW5lcmljQWRkaXRpb25hbFVzZXJJbmZvIGltcGxlbWVudHMgQWRkaXRpb25hbFVzZXJJbmZvIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgaXNOZXdVc2VyOiBib29sZWFuLFxuICAgIHJlYWRvbmx5IHByb3ZpZGVySWQ6IFByb3ZpZGVySWQgfCBzdHJpbmcgfCBudWxsLFxuICAgIHJlYWRvbmx5IHByb2ZpbGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge31cbiAgKSB7fVxufVxuXG5jbGFzcyBGZWRlcmF0ZWRBZGRpdGlvbmFsVXNlckluZm9XaXRoVXNlcm5hbWUgZXh0ZW5kcyBHZW5lcmljQWRkaXRpb25hbFVzZXJJbmZvIHtcbiAgY29uc3RydWN0b3IoXG4gICAgaXNOZXdVc2VyOiBib29sZWFuLFxuICAgIHByb3ZpZGVySWQ6IFByb3ZpZGVySWQsXG4gICAgcHJvZmlsZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgcmVhZG9ubHkgdXNlcm5hbWU6IHN0cmluZyB8IG51bGxcbiAgKSB7XG4gICAgc3VwZXIoaXNOZXdVc2VyLCBwcm92aWRlcklkLCBwcm9maWxlKTtcbiAgfVxufVxuXG5jbGFzcyBGYWNlYm9va0FkZGl0aW9uYWxVc2VySW5mbyBleHRlbmRzIEdlbmVyaWNBZGRpdGlvbmFsVXNlckluZm8ge1xuICBjb25zdHJ1Y3Rvcihpc05ld1VzZXI6IGJvb2xlYW4sIHByb2ZpbGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgc3VwZXIoaXNOZXdVc2VyLCBQcm92aWRlcklkLkZBQ0VCT09LLCBwcm9maWxlKTtcbiAgfVxufVxuXG5jbGFzcyBHaXRodWJBZGRpdGlvbmFsVXNlckluZm8gZXh0ZW5kcyBGZWRlcmF0ZWRBZGRpdGlvbmFsVXNlckluZm9XaXRoVXNlcm5hbWUge1xuICBjb25zdHJ1Y3Rvcihpc05ld1VzZXI6IGJvb2xlYW4sIHByb2ZpbGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgc3VwZXIoXG4gICAgICBpc05ld1VzZXIsXG4gICAgICBQcm92aWRlcklkLkdJVEhVQixcbiAgICAgIHByb2ZpbGUsXG4gICAgICB0eXBlb2YgcHJvZmlsZT8ubG9naW4gPT09ICdzdHJpbmcnID8gcHJvZmlsZT8ubG9naW4gOiBudWxsXG4gICAgKTtcbiAgfVxufVxuXG5jbGFzcyBHb29nbGVBZGRpdGlvbmFsVXNlckluZm8gZXh0ZW5kcyBHZW5lcmljQWRkaXRpb25hbFVzZXJJbmZvIHtcbiAgY29uc3RydWN0b3IoaXNOZXdVc2VyOiBib29sZWFuLCBwcm9maWxlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIHN1cGVyKGlzTmV3VXNlciwgUHJvdmlkZXJJZC5HT09HTEUsIHByb2ZpbGUpO1xuICB9XG59XG5cbmNsYXNzIFR3aXR0ZXJBZGRpdGlvbmFsVXNlckluZm8gZXh0ZW5kcyBGZWRlcmF0ZWRBZGRpdGlvbmFsVXNlckluZm9XaXRoVXNlcm5hbWUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBpc05ld1VzZXI6IGJvb2xlYW4sXG4gICAgcHJvZmlsZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgc2NyZWVuTmFtZTogc3RyaW5nIHwgbnVsbFxuICApIHtcbiAgICBzdXBlcihpc05ld1VzZXIsIFByb3ZpZGVySWQuVFdJVFRFUiwgcHJvZmlsZSwgc2NyZWVuTmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBFeHRyYWN0cyBwcm92aWRlciBzcGVjaWZpYyB7QGxpbmsgQWRkaXRpb25hbFVzZXJJbmZvfSBmb3IgdGhlIGdpdmVuIGNyZWRlbnRpYWwuXG4gKlxuICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRpdGlvbmFsVXNlckluZm8oXG4gIHVzZXJDcmVkZW50aWFsOiBVc2VyQ3JlZGVudGlhbFxuKTogQWRkaXRpb25hbFVzZXJJbmZvIHwgbnVsbCB7XG4gIGNvbnN0IHsgdXNlciwgX3Rva2VuUmVzcG9uc2UgfSA9IHVzZXJDcmVkZW50aWFsIGFzIFVzZXJDcmVkZW50aWFsSW50ZXJuYWw7XG4gIGlmICh1c2VyLmlzQW5vbnltb3VzICYmICFfdG9rZW5SZXNwb25zZSkge1xuICAgIC8vIEhhbmRsZSB0aGUgc3BlY2lhbCBjYXNlIHdoZXJlIHNpZ25JbkFub255bW91c2x5KCkgZ2V0cyBjYWxsZWQgdHdpY2UuXG4gICAgLy8gTm8gbmV0d29yayBjYWxsIGlzIG1hZGUgc28gdGhlcmUncyBub3RoaW5nIHRvIGFjdHVhbGx5IGZpbGwgdGhpcyBpblxuICAgIHJldHVybiB7XG4gICAgICBwcm92aWRlcklkOiBudWxsLFxuICAgICAgaXNOZXdVc2VyOiBmYWxzZSxcbiAgICAgIHByb2ZpbGU6IG51bGxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIF9mcm9tSWRUb2tlblJlc3BvbnNlKF90b2tlblJlc3BvbnNlKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQge1xuICBBdXRoLFxuICBOZXh0T3JPYnNlcnZlcixcbiAgUGVyc2lzdGVuY2UsXG4gIFVzZXIsXG4gIENvbXBsZXRlRm4sXG4gIEVycm9yRm4sXG4gIFVuc3Vic2NyaWJlLFxuICBQYXNzd29yZFZhbGlkYXRpb25TdGF0dXNcbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IF9pbml0aWFsaXplUmVjYXB0Y2hhQ29uZmlnIH0gZnJvbSAnLi4vcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXInO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5cbmV4cG9ydCB7XG4gIGRlYnVnRXJyb3JNYXAsXG4gIHByb2RFcnJvck1hcCxcbiAgQVVUSF9FUlJPUl9DT0RFU19NQVBfRE9fTk9UX1VTRV9JTlRFUk5BTExZIGFzIEF1dGhFcnJvckNvZGVzXG59IGZyb20gJy4vZXJyb3JzJztcblxuLy8gTm9uLW9wdGlvbmFsIGF1dGggbWV0aG9kcy5cbi8qKlxuICogQ2hhbmdlcyB0aGUgdHlwZSBvZiBwZXJzaXN0ZW5jZSBvbiB0aGUge0BsaW5rIEF1dGh9IGluc3RhbmNlIGZvciB0aGUgY3VycmVudGx5IHNhdmVkXG4gKiBgQXV0aGAgc2Vzc2lvbiBhbmQgYXBwbGllcyB0aGlzIHR5cGUgb2YgcGVyc2lzdGVuY2UgZm9yIGZ1dHVyZSBzaWduLWluIHJlcXVlc3RzLCBpbmNsdWRpbmdcbiAqIHNpZ24taW4gd2l0aCByZWRpcmVjdCByZXF1ZXN0cy5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhpcyBtYWtlcyBpdCBlYXN5IGZvciBhIHVzZXIgc2lnbmluZyBpbiB0byBzcGVjaWZ5IHdoZXRoZXIgdGhlaXIgc2Vzc2lvbiBzaG91bGQgYmVcbiAqIHJlbWVtYmVyZWQgb3Igbm90LiBJdCBhbHNvIG1ha2VzIGl0IGVhc2llciB0byBuZXZlciBwZXJzaXN0IHRoZSBgQXV0aGAgc3RhdGUgZm9yIGFwcGxpY2F0aW9uc1xuICogdGhhdCBhcmUgc2hhcmVkIGJ5IG90aGVyIHVzZXJzIG9yIGhhdmUgc2Vuc2l0aXZlIGRhdGEuXG4gKlxuICogVGhpcyBtZXRob2QgZG9lcyBub3Qgd29yayBpbiBhIE5vZGUuanMgZW52aXJvbm1lbnQgb3Igd2l0aCB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHNldFBlcnNpc3RlbmNlKGF1dGgsIGJyb3dzZXJTZXNzaW9uUGVyc2lzdGVuY2UpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIHBlcnNpc3RlbmNlIC0gVGhlIHtAbGluayBQZXJzaXN0ZW5jZX0gdG8gdXNlLlxuICogQHJldHVybnMgQSBgUHJvbWlzZWAgdGhhdCByZXNvbHZlcyBvbmNlIHRoZSBwZXJzaXN0ZW5jZSBjaGFuZ2UgaGFzIGNvbXBsZXRlZFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFBlcnNpc3RlbmNlKFxuICBhdXRoOiBBdXRoLFxuICBwZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2Vcbik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpLnNldFBlcnNpc3RlbmNlKHBlcnNpc3RlbmNlKTtcbn1cblxuLyoqXG4gKiBMb2FkcyB0aGUgcmVDQVBUQ0hBIGNvbmZpZ3VyYXRpb24gaW50byB0aGUgYEF1dGhgIGluc3RhbmNlLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIHdpbGwgbG9hZCB0aGUgcmVDQVBUQ0hBIGNvbmZpZywgd2hpY2ggaW5kaWNhdGVzIHdoZXRoZXIgdGhlIHJlQ0FQVENIQVxuICogdmVyaWZpY2F0aW9uIGZsb3cgc2hvdWxkIGJlIHRyaWdnZXJlZCBmb3IgZWFjaCBhdXRoIHByb3ZpZGVyLCBpbnRvIHRoZVxuICogY3VycmVudCBBdXRoIHNlc3Npb24uXG4gKlxuICogSWYgaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZygpIGlzIG5vdCBpbnZva2VkLCB0aGUgYXV0aCBmbG93IHdpbGwgYWx3YXlzIHN0YXJ0XG4gKiB3aXRob3V0IHJlQ0FQVENIQSB2ZXJpZmljYXRpb24uIElmIHRoZSBwcm92aWRlciBpcyBjb25maWd1cmVkIHRvIHJlcXVpcmUgcmVDQVBUQ0hBXG4gKiB2ZXJpZmljYXRpb24sIHRoZSBTREsgd2lsbCB0cmFuc3BhcmVudGx5IGxvYWQgdGhlIHJlQ0FQVENIQSBjb25maWcgYW5kIHJlc3RhcnQgdGhlXG4gKiBhdXRoIGZsb3dzLlxuICpcbiAqIFRodXMsIGJ5IGNhbGxpbmcgdGhpcyBvcHRpb25hbCBtZXRob2QsIHlvdSB3aWxsIHJlZHVjZSB0aGUgbGF0ZW5jeSBvZiBmdXR1cmUgYXV0aCBmbG93cy5cbiAqIExvYWRpbmcgdGhlIHJlQ0FQVENIQSBjb25maWcgZWFybHkgd2lsbCBhbHNvIGVuaGFuY2UgdGhlIHNpZ25hbCBjb2xsZWN0ZWQgYnkgcmVDQVBUQ0hBLlxuICpcbiAqIFRoaXMgbWV0aG9kIGRvZXMgbm90IHdvcmsgaW4gYSBOb2RlLmpzIGVudmlyb25tZW50LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBpbml0aWFsaXplUmVjYXB0Y2hhQ29uZmlnKGF1dGgpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVSZWNhcHRjaGFDb25maWcoYXV0aDogQXV0aCk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gX2luaXRpYWxpemVSZWNhcHRjaGFDb25maWcoYXV0aCk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHRoZSBwYXNzd29yZCBhZ2FpbnN0IHRoZSBwYXNzd29yZCBwb2xpY3kgY29uZmlndXJlZCBmb3IgdGhlIHByb2plY3Qgb3IgdGVuYW50LlxuICpcbiAqIEByZW1hcmtzXG4gKiBJZiBubyB0ZW5hbnQgSUQgaXMgc2V0IG9uIHRoZSBgQXV0aGAgaW5zdGFuY2UsIHRoZW4gdGhpcyBtZXRob2Qgd2lsbCB1c2UgdGhlIHBhc3N3b3JkXG4gKiBwb2xpY3kgY29uZmlndXJlZCBmb3IgdGhlIHByb2plY3QuIE90aGVyd2lzZSwgdGhpcyBtZXRob2Qgd2lsbCB1c2UgdGhlIHBvbGljeSBjb25maWd1cmVkXG4gKiBmb3IgdGhlIHRlbmFudC4gSWYgYSBwYXNzd29yZCBwb2xpY3kgaGFzIG5vdCBiZWVuIGNvbmZpZ3VyZWQsIHRoZW4gdGhlIGRlZmF1bHQgcG9saWN5XG4gKiBjb25maWd1cmVkIGZvciBhbGwgcHJvamVjdHMgd2lsbCBiZSB1c2VkLlxuICpcbiAqIElmIGFuIGF1dGggZmxvdyBmYWlscyBiZWNhdXNlIGEgc3VibWl0dGVkIHBhc3N3b3JkIGRvZXMgbm90IG1lZXQgdGhlIHBhc3N3b3JkIHBvbGljeVxuICogcmVxdWlyZW1lbnRzIGFuZCB0aGlzIG1ldGhvZCBoYXMgcHJldmlvdXNseSBiZWVuIGNhbGxlZCwgdGhlbiB0aGlzIG1ldGhvZCB3aWxsIHVzZSB0aGVcbiAqIG1vc3QgcmVjZW50IHBvbGljeSBhdmFpbGFibGUgd2hlbiBjYWxsZWQgYWdhaW4uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHZhbGlkYXRlUGFzc3dvcmQoYXV0aCwgJ3NvbWUtcGFzc3dvcmQnKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBhdXRoIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gcGFzc3dvcmQgVGhlIHBhc3N3b3JkIHRvIHZhbGlkYXRlLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlUGFzc3dvcmQoXG4gIGF1dGg6IEF1dGgsXG4gIHBhc3N3b3JkOiBzdHJpbmdcbik6IFByb21pc2U8UGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzPiB7XG4gIGNvbnN0IGF1dGhJbnRlcm5hbCA9IF9jYXN0QXV0aChhdXRoKTtcbiAgcmV0dXJuIGF1dGhJbnRlcm5hbC52YWxpZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKTtcbn1cblxuLyoqXG4gKiBBZGRzIGFuIG9ic2VydmVyIGZvciBjaGFuZ2VzIHRvIHRoZSBzaWduZWQtaW4gdXNlcidzIElEIHRva2VuLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGluY2x1ZGVzIHNpZ24taW4sIHNpZ24tb3V0LCBhbmQgdG9rZW4gcmVmcmVzaCBldmVudHMuXG4gKiBUaGlzIHdpbGwgbm90IGJlIHRyaWdnZXJlZCBhdXRvbWF0aWNhbGx5IHVwb24gSUQgdG9rZW4gZXhwaXJhdGlvbi4gVXNlIHtAbGluayBVc2VyLmdldElkVG9rZW59IHRvIHJlZnJlc2ggdGhlIElEIHRva2VuLlxuICpcbiAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqIEBwYXJhbSBuZXh0T3JPYnNlcnZlciAtIGNhbGxiYWNrIHRyaWdnZXJlZCBvbiBjaGFuZ2UuXG4gKiBAcGFyYW0gZXJyb3IgLSBEZXByZWNhdGVkLiBUaGlzIGNhbGxiYWNrIGlzIG5ldmVyIHRyaWdnZXJlZC4gRXJyb3JzXG4gKiBvbiBzaWduaW5nIGluL291dCBjYW4gYmUgY2F1Z2h0IGluIHByb21pc2VzIHJldHVybmVkIGZyb21cbiAqIHNpZ24taW4vc2lnbi1vdXQgZnVuY3Rpb25zLlxuICogQHBhcmFtIGNvbXBsZXRlZCAtIERlcHJlY2F0ZWQuIFRoaXMgY2FsbGJhY2sgaXMgbmV2ZXIgdHJpZ2dlcmVkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uSWRUb2tlbkNoYW5nZWQoXG4gIGF1dGg6IEF1dGgsXG4gIG5leHRPck9ic2VydmVyOiBOZXh0T3JPYnNlcnZlcjxVc2VyPixcbiAgZXJyb3I/OiBFcnJvckZuLFxuICBjb21wbGV0ZWQ/OiBDb21wbGV0ZUZuXG4pOiBVbnN1YnNjcmliZSB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkub25JZFRva2VuQ2hhbmdlZChcbiAgICBuZXh0T3JPYnNlcnZlcixcbiAgICBlcnJvcixcbiAgICBjb21wbGV0ZWRcbiAgKTtcbn1cbi8qKlxuICogQWRkcyBhIGJsb2NraW5nIGNhbGxiYWNrIHRoYXQgcnVucyBiZWZvcmUgYW4gYXV0aCBzdGF0ZSBjaGFuZ2VcbiAqIHNldHMgYSBuZXcgdXNlci5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gY2FsbGJhY2sgLSBjYWxsYmFjayB0cmlnZ2VyZWQgYmVmb3JlIG5ldyB1c2VyIHZhbHVlIGlzIHNldC5cbiAqICAgSWYgdGhpcyB0aHJvd3MsIGl0IGJsb2NrcyB0aGUgdXNlciBmcm9tIGJlaW5nIHNldC5cbiAqIEBwYXJhbSBvbkFib3J0IC0gY2FsbGJhY2sgdHJpZ2dlcmVkIGlmIGEgbGF0ZXIgYGJlZm9yZUF1dGhTdGF0ZUNoYW5nZWQoKWBcbiAqICAgY2FsbGJhY2sgdGhyb3dzLCBhbGxvd2luZyB5b3UgdG8gdW5kbyBhbnkgc2lkZSBlZmZlY3RzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmVmb3JlQXV0aFN0YXRlQ2hhbmdlZChcbiAgYXV0aDogQXV0aCxcbiAgY2FsbGJhY2s6ICh1c2VyOiBVc2VyIHwgbnVsbCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4sXG4gIG9uQWJvcnQ/OiAoKSA9PiB2b2lkXG4pOiBVbnN1YnNjcmliZSB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkuYmVmb3JlQXV0aFN0YXRlQ2hhbmdlZChjYWxsYmFjaywgb25BYm9ydCk7XG59XG4vKipcbiAqIEFkZHMgYW4gb2JzZXJ2ZXIgZm9yIGNoYW5nZXMgdG8gdGhlIHVzZXIncyBzaWduLWluIHN0YXRlLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUbyBrZWVwIHRoZSBvbGQgYmVoYXZpb3IsIHNlZSB7QGxpbmsgb25JZFRva2VuQ2hhbmdlZH0uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIG5leHRPck9ic2VydmVyIC0gY2FsbGJhY2sgdHJpZ2dlcmVkIG9uIGNoYW5nZS5cbiAqIEBwYXJhbSBlcnJvciAtIERlcHJlY2F0ZWQuIFRoaXMgY2FsbGJhY2sgaXMgbmV2ZXIgdHJpZ2dlcmVkLiBFcnJvcnNcbiAqIG9uIHNpZ25pbmcgaW4vb3V0IGNhbiBiZSBjYXVnaHQgaW4gcHJvbWlzZXMgcmV0dXJuZWQgZnJvbVxuICogc2lnbi1pbi9zaWduLW91dCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0gY29tcGxldGVkIC0gRGVwcmVjYXRlZC4gVGhpcyBjYWxsYmFjayBpcyBuZXZlciB0cmlnZ2VyZWQuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25BdXRoU3RhdGVDaGFuZ2VkKFxuICBhdXRoOiBBdXRoLFxuICBuZXh0T3JPYnNlcnZlcjogTmV4dE9yT2JzZXJ2ZXI8VXNlcj4sXG4gIGVycm9yPzogRXJyb3JGbixcbiAgY29tcGxldGVkPzogQ29tcGxldGVGblxuKTogVW5zdWJzY3JpYmUge1xuICByZXR1cm4gZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpLm9uQXV0aFN0YXRlQ2hhbmdlZChcbiAgICBuZXh0T3JPYnNlcnZlcixcbiAgICBlcnJvcixcbiAgICBjb21wbGV0ZWRcbiAgKTtcbn1cbi8qKlxuICogU2V0cyB0aGUgY3VycmVudCBsYW5ndWFnZSB0byB0aGUgZGVmYXVsdCBkZXZpY2UvYnJvd3NlciBwcmVmZXJlbmNlLlxuICpcbiAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VEZXZpY2VMYW5ndWFnZShhdXRoOiBBdXRoKTogdm9pZCB7XG4gIGdldE1vZHVsYXJJbnN0YW5jZShhdXRoKS51c2VEZXZpY2VMYW5ndWFnZSgpO1xufVxuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzZXRzIHRoZSBwcm92aWRlZCB1c2VyIGFzIHtAbGluayBBdXRoLmN1cnJlbnRVc2VyfSBvbiB0aGVcbiAqIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqXG4gKiBAcmVtYXJrc1xuICogQSBuZXcgaW5zdGFuY2UgY29weSBvZiB0aGUgdXNlciBwcm92aWRlZCB3aWxsIGJlIG1hZGUgYW5kIHNldCBhcyBjdXJyZW50VXNlci5cbiAqXG4gKiBUaGlzIHdpbGwgdHJpZ2dlciB7QGxpbmsgb25BdXRoU3RhdGVDaGFuZ2VkfSBhbmQge0BsaW5rIG9uSWRUb2tlbkNoYW5nZWR9IGxpc3RlbmVyc1xuICogbGlrZSBvdGhlciBzaWduIGluIG1ldGhvZHMuXG4gKlxuICogVGhlIG9wZXJhdGlvbiBmYWlscyB3aXRoIGFuIGVycm9yIGlmIHRoZSB1c2VyIHRvIGJlIHVwZGF0ZWQgYmVsb25ncyB0byBhIGRpZmZlcmVudCBGaXJlYmFzZVxuICogcHJvamVjdC5cbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gdXNlciAtIFRoZSBuZXcge0BsaW5rIFVzZXJ9LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUN1cnJlbnRVc2VyKFxuICBhdXRoOiBBdXRoLFxuICB1c2VyOiBVc2VyIHwgbnVsbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkudXBkYXRlQ3VycmVudFVzZXIodXNlcik7XG59XG4vKipcbiAqIFNpZ25zIG91dCB0aGUgY3VycmVudCB1c2VyLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2lnbk91dChhdXRoOiBBdXRoKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkuc2lnbk91dCgpO1xufVxuXG4vKipcbiAqIFJldm9rZXMgdGhlIGdpdmVuIGFjY2VzcyB0b2tlbi4gQ3VycmVudGx5IG9ubHkgc3VwcG9ydHMgQXBwbGUgT0F1dGggYWNjZXNzIHRva2Vucy5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgQXBwbGUgT0F1dGggYWNjZXNzIHRva2VuLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9rZUFjY2Vzc1Rva2VuKGF1dGg6IEF1dGgsIHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICByZXR1cm4gYXV0aEludGVybmFsLnJldm9rZUFjY2Vzc1Rva2VuKHRva2VuKTtcbn1cblxuZXhwb3J0IHsgaW5pdGlhbGl6ZUF1dGggfSBmcm9tICcuL2F1dGgvaW5pdGlhbGl6ZSc7XG5leHBvcnQgeyBjb25uZWN0QXV0aEVtdWxhdG9yIH0gZnJvbSAnLi9hdXRoL2VtdWxhdG9yJztcblxuLy8gY3JlZGVudGlhbHNcbmV4cG9ydCB7IEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi9jcmVkZW50aWFscyc7XG5leHBvcnQgeyBFbWFpbEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi9jcmVkZW50aWFscy9lbWFpbCc7XG5leHBvcnQgeyBPQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2NyZWRlbnRpYWxzL29hdXRoJztcbmV4cG9ydCB7IFBob25lQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2NyZWRlbnRpYWxzL3Bob25lJztcblxuLy8gcGVyc2lzdGVuY2VcbmV4cG9ydCB7IGluTWVtb3J5UGVyc2lzdGVuY2UgfSBmcm9tICcuL3BlcnNpc3RlbmNlL2luX21lbW9yeSc7XG5cbi8vIHByb3ZpZGVyc1xuZXhwb3J0IHsgRW1haWxBdXRoUHJvdmlkZXIgfSBmcm9tICcuL3Byb3ZpZGVycy9lbWFpbCc7XG5leHBvcnQgeyBGYWNlYm9va0F1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL2ZhY2Vib29rJztcbmV4cG9ydCB7IEN1c3RvbVBhcmFtZXRlcnMgfSBmcm9tICcuL3Byb3ZpZGVycy9mZWRlcmF0ZWQnO1xuZXhwb3J0IHsgR29vZ2xlQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlcnMvZ29vZ2xlJztcbmV4cG9ydCB7IEdpdGh1YkF1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL2dpdGh1Yic7XG5leHBvcnQgeyBPQXV0aFByb3ZpZGVyLCBPQXV0aENyZWRlbnRpYWxPcHRpb25zIH0gZnJvbSAnLi9wcm92aWRlcnMvb2F1dGgnO1xuZXhwb3J0IHsgU0FNTEF1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL3NhbWwnO1xuZXhwb3J0IHsgVHdpdHRlckF1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL3R3aXR0ZXInO1xuXG4vLyBzdHJhdGVnaWVzXG5leHBvcnQgeyBzaWduSW5Bbm9ueW1vdXNseSB9IGZyb20gJy4vc3RyYXRlZ2llcy9hbm9ueW1vdXMnO1xuZXhwb3J0IHtcbiAgc2lnbkluV2l0aENyZWRlbnRpYWwsXG4gIGxpbmtXaXRoQ3JlZGVudGlhbCxcbiAgcmVhdXRoZW50aWNhdGVXaXRoQ3JlZGVudGlhbFxufSBmcm9tICcuL3N0cmF0ZWdpZXMvY3JlZGVudGlhbCc7XG5leHBvcnQgeyBzaWduSW5XaXRoQ3VzdG9tVG9rZW4gfSBmcm9tICcuL3N0cmF0ZWdpZXMvY3VzdG9tX3Rva2VuJztcbmV4cG9ydCB7XG4gIHNlbmRQYXNzd29yZFJlc2V0RW1haWwsXG4gIGNvbmZpcm1QYXNzd29yZFJlc2V0LFxuICBhcHBseUFjdGlvbkNvZGUsXG4gIGNoZWNrQWN0aW9uQ29kZSxcbiAgdmVyaWZ5UGFzc3dvcmRSZXNldENvZGUsXG4gIGNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZCxcbiAgc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmRcbn0gZnJvbSAnLi9zdHJhdGVnaWVzL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5leHBvcnQge1xuICBzZW5kU2lnbkluTGlua1RvRW1haWwsXG4gIGlzU2lnbkluV2l0aEVtYWlsTGluayxcbiAgc2lnbkluV2l0aEVtYWlsTGlua1xufSBmcm9tICcuL3N0cmF0ZWdpZXMvZW1haWxfbGluayc7XG5leHBvcnQge1xuICBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbCxcbiAgc2VuZEVtYWlsVmVyaWZpY2F0aW9uLFxuICB2ZXJpZnlCZWZvcmVVcGRhdGVFbWFpbFxufSBmcm9tICcuL3N0cmF0ZWdpZXMvZW1haWwnO1xuXG4vLyBjb3JlXG5leHBvcnQgeyBBY3Rpb25Db2RlVVJMLCBwYXJzZUFjdGlvbkNvZGVVUkwgfSBmcm9tICcuL2FjdGlvbl9jb2RlX3VybCc7XG5cbi8vIHVzZXJcbmV4cG9ydCB7XG4gIHVwZGF0ZVByb2ZpbGUsXG4gIHVwZGF0ZUVtYWlsLFxuICB1cGRhdGVQYXNzd29yZFxufSBmcm9tICcuL3VzZXIvYWNjb3VudF9pbmZvJztcbmV4cG9ydCB7IGdldElkVG9rZW4sIGdldElkVG9rZW5SZXN1bHQgfSBmcm9tICcuL3VzZXIvaWRfdG9rZW5fcmVzdWx0JztcbmV4cG9ydCB7IHVubGluayB9IGZyb20gJy4vdXNlci9saW5rX3VubGluayc7XG5leHBvcnQgeyBnZXRBZGRpdGlvbmFsVXNlckluZm8gfSBmcm9tICcuL3VzZXIvYWRkaXRpb25hbF91c2VyX2luZm8nO1xuXG4vLyBOb24tb3B0aW9uYWwgdXNlciBtZXRob2RzLlxuZXhwb3J0IHsgcmVsb2FkIH0gZnJvbSAnLi91c2VyL3JlbG9hZCc7XG4vKipcbiAqIERlbGV0ZXMgYW5kIHNpZ25zIG91dCB0aGUgdXNlci5cbiAqXG4gKiBAcmVtYXJrc1xuICogSW1wb3J0YW50OiB0aGlzIGlzIGEgc2VjdXJpdHktc2Vuc2l0aXZlIG9wZXJhdGlvbiB0aGF0IHJlcXVpcmVzIHRoZSB1c2VyIHRvIGhhdmUgcmVjZW50bHlcbiAqIHNpZ25lZCBpbi4gSWYgdGhpcyByZXF1aXJlbWVudCBpc24ndCBtZXQsIGFzayB0aGUgdXNlciB0byBhdXRoZW50aWNhdGUgYWdhaW4gYW5kIHRoZW4gY2FsbFxuICoge0BsaW5rIHJlYXV0aGVudGljYXRlV2l0aENyZWRlbnRpYWx9LlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlVXNlcih1c2VyOiBVc2VyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UodXNlcikuZGVsZXRlKCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvclNlc3Npb24gfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgZW51bSBNdWx0aUZhY3RvclNlc3Npb25UeXBlIHtcbiAgRU5ST0xMID0gJ2Vucm9sbCcsXG4gIFNJR05fSU4gPSAnc2lnbmluJ1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplZE11bHRpRmFjdG9yU2Vzc2lvbiB7XG4gIG11bHRpRmFjdG9yU2Vzc2lvbjoge1xuICAgIGlkVG9rZW4/OiBzdHJpbmc7XG4gICAgcGVuZGluZ0NyZWRlbnRpYWw/OiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBNdWx0aUZhY3RvclNlc3Npb25JbXBsIGltcGxlbWVudHMgTXVsdGlGYWN0b3JTZXNzaW9uIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSB0eXBlOiBNdWx0aUZhY3RvclNlc3Npb25UeXBlLFxuICAgIHJlYWRvbmx5IGNyZWRlbnRpYWw6IHN0cmluZyxcbiAgICByZWFkb25seSB1c2VyPzogVXNlckludGVybmFsXG4gICkge31cblxuICBzdGF0aWMgX2Zyb21JZHRva2VuKFxuICAgIGlkVG9rZW46IHN0cmluZyxcbiAgICB1c2VyPzogVXNlckludGVybmFsXG4gICk6IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwge1xuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JTZXNzaW9uSW1wbChcbiAgICAgIE11bHRpRmFjdG9yU2Vzc2lvblR5cGUuRU5ST0xMLFxuICAgICAgaWRUb2tlbixcbiAgICAgIHVzZXJcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tTWZhUGVuZGluZ0NyZWRlbnRpYWwoXG4gICAgbWZhUGVuZGluZ0NyZWRlbnRpYWw6IHN0cmluZ1xuICApOiBNdWx0aUZhY3RvclNlc3Npb25JbXBsIHtcbiAgICByZXR1cm4gbmV3IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwoXG4gICAgICBNdWx0aUZhY3RvclNlc3Npb25UeXBlLlNJR05fSU4sXG4gICAgICBtZmFQZW5kaW5nQ3JlZGVudGlhbFxuICAgICk7XG4gIH1cblxuICB0b0pTT04oKTogU2VyaWFsaXplZE11bHRpRmFjdG9yU2Vzc2lvbiB7XG4gICAgY29uc3Qga2V5ID1cbiAgICAgIHRoaXMudHlwZSA9PT0gTXVsdGlGYWN0b3JTZXNzaW9uVHlwZS5FTlJPTExcbiAgICAgICAgPyAnaWRUb2tlbidcbiAgICAgICAgOiAncGVuZGluZ0NyZWRlbnRpYWwnO1xuICAgIHJldHVybiB7XG4gICAgICBtdWx0aUZhY3RvclNlc3Npb246IHtcbiAgICAgICAgW2tleV06IHRoaXMuY3JlZGVudGlhbFxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgZnJvbUpTT04oXG4gICAgb2JqOiBQYXJ0aWFsPFNlcmlhbGl6ZWRNdWx0aUZhY3RvclNlc3Npb24+XG4gICk6IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwgfCBudWxsIHtcbiAgICBpZiAob2JqPy5tdWx0aUZhY3RvclNlc3Npb24pIHtcbiAgICAgIGlmIChvYmoubXVsdGlGYWN0b3JTZXNzaW9uPy5wZW5kaW5nQ3JlZGVudGlhbCkge1xuICAgICAgICByZXR1cm4gTXVsdGlGYWN0b3JTZXNzaW9uSW1wbC5fZnJvbU1mYVBlbmRpbmdDcmVkZW50aWFsKFxuICAgICAgICAgIG9iai5tdWx0aUZhY3RvclNlc3Npb24ucGVuZGluZ0NyZWRlbnRpYWxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAob2JqLm11bHRpRmFjdG9yU2Vzc2lvbj8uaWRUb2tlbikge1xuICAgICAgICByZXR1cm4gTXVsdGlGYWN0b3JTZXNzaW9uSW1wbC5fZnJvbUlkdG9rZW4oXG4gICAgICAgICAgb2JqLm11bHRpRmFjdG9yU2Vzc2lvbi5pZFRva2VuXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgQXV0aCxcbiAgTXVsdGlGYWN0b3JSZXNvbHZlcixcbiAgVXNlckNyZWRlbnRpYWwsXG4gIE11bHRpRmFjdG9yRXJyb3Jcbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbXBsIH0gZnJvbSAnLi4vY29yZS91c2VyL3VzZXJfY3JlZGVudGlhbF9pbXBsJztcbmltcG9ydCB7IF9hc3NlcnQsIF9mYWlsIH0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbEludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwgfSBmcm9tICcuL21mYV9hc3NlcnRpb24nO1xuaW1wb3J0IHsgTXVsdGlGYWN0b3JFcnJvciBhcyBNdWx0aUZhY3RvckVycm9ySW50ZXJuYWwgfSBmcm9tICcuL21mYV9lcnJvcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckluZm9JbXBsIH0gZnJvbSAnLi9tZmFfaW5mbyc7XG5pbXBvcnQgeyBNdWx0aUZhY3RvclNlc3Npb25JbXBsIH0gZnJvbSAnLi9tZmFfc2Vzc2lvbic7XG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vbW9kZWwvZW51bXMnO1xuXG5leHBvcnQgY2xhc3MgTXVsdGlGYWN0b3JSZXNvbHZlckltcGwgaW1wbGVtZW50cyBNdWx0aUZhY3RvclJlc29sdmVyIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBzZXNzaW9uOiBNdWx0aUZhY3RvclNlc3Npb25JbXBsLFxuICAgIHJlYWRvbmx5IGhpbnRzOiBNdWx0aUZhY3RvckluZm9JbXBsW10sXG4gICAgcHJpdmF0ZSByZWFkb25seSBzaWduSW5SZXNvbHZlcjogKFxuICAgICAgYXNzZXJ0aW9uOiBNdWx0aUZhY3RvckFzc2VydGlvbkltcGxcbiAgICApID0+IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbnRlcm5hbD5cbiAgKSB7fVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tRXJyb3IoXG4gICAgYXV0aEV4dGVybjogQXV0aCxcbiAgICBlcnJvcjogTXVsdGlGYWN0b3JFcnJvckludGVybmFsXG4gICk6IE11bHRpRmFjdG9yUmVzb2x2ZXJJbXBsIHtcbiAgICBjb25zdCBhdXRoID0gX2Nhc3RBdXRoKGF1dGhFeHRlcm4pO1xuICAgIGNvbnN0IHNlcnZlclJlc3BvbnNlID0gZXJyb3IuY3VzdG9tRGF0YS5fc2VydmVyUmVzcG9uc2U7XG4gICAgY29uc3QgaGludHMgPSAoc2VydmVyUmVzcG9uc2UubWZhSW5mbyB8fCBbXSkubWFwKGVucm9sbG1lbnQgPT5cbiAgICAgIE11bHRpRmFjdG9ySW5mb0ltcGwuX2Zyb21TZXJ2ZXJSZXNwb25zZShhdXRoLCBlbnJvbGxtZW50KVxuICAgICk7XG5cbiAgICBfYXNzZXJ0KFxuICAgICAgc2VydmVyUmVzcG9uc2UubWZhUGVuZGluZ0NyZWRlbnRpYWwsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwuX2Zyb21NZmFQZW5kaW5nQ3JlZGVudGlhbChcbiAgICAgIHNlcnZlclJlc3BvbnNlLm1mYVBlbmRpbmdDcmVkZW50aWFsXG4gICAgKTtcblxuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JSZXNvbHZlckltcGwoXG4gICAgICBzZXNzaW9uLFxuICAgICAgaGludHMsXG4gICAgICBhc3luYyAoXG4gICAgICAgIGFzc2VydGlvbjogTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsXG4gICAgICApOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsSW50ZXJuYWw+ID0+IHtcbiAgICAgICAgY29uc3QgbWZhUmVzcG9uc2UgPSBhd2FpdCBhc3NlcnRpb24uX3Byb2Nlc3MoYXV0aCwgc2Vzc2lvbik7XG4gICAgICAgIC8vIENsZWFyIG91dCB0aGUgdW5uZWVkZWQgZmllbGRzIGZyb20gdGhlIG9sZCBsb2dpbiByZXNwb25zZVxuICAgICAgICBkZWxldGUgc2VydmVyUmVzcG9uc2UubWZhSW5mbztcbiAgICAgICAgZGVsZXRlIHNlcnZlclJlc3BvbnNlLm1mYVBlbmRpbmdDcmVkZW50aWFsO1xuXG4gICAgICAgIC8vIFVzZSBpbiB0aGUgbmV3IHRva2VuICYgcmVmcmVzaCB0b2tlbiBpbiB0aGUgb2xkIHJlc3BvbnNlXG4gICAgICAgIGNvbnN0IGlkVG9rZW5SZXNwb25zZSA9IHtcbiAgICAgICAgICAuLi5zZXJ2ZXJSZXNwb25zZSxcbiAgICAgICAgICBpZFRva2VuOiBtZmFSZXNwb25zZS5pZFRva2VuLFxuICAgICAgICAgIHJlZnJlc2hUb2tlbjogbWZhUmVzcG9uc2UucmVmcmVzaFRva2VuXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gVE9ETzogd2Ugc2hvdWxkIGNvbGxhcHNlIHRoaXMgc3dpdGNoIHN0YXRlbWVudCBpbnRvIFVzZXJDcmVkZW50aWFsSW1wbC5fZm9yT3BlcmF0aW9uIGFuZCBoYXZlIGl0IHN1cHBvcnQgdGhlIFNJR05fSU4gY2FzZVxuICAgICAgICBzd2l0Y2ggKGVycm9yLm9wZXJhdGlvblR5cGUpIHtcbiAgICAgICAgICBjYXNlIE9wZXJhdGlvblR5cGUuU0lHTl9JTjpcbiAgICAgICAgICAgIGNvbnN0IHVzZXJDcmVkZW50aWFsID1cbiAgICAgICAgICAgICAgYXdhaXQgVXNlckNyZWRlbnRpYWxJbXBsLl9mcm9tSWRUb2tlblJlc3BvbnNlKFxuICAgICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgICAgZXJyb3Iub3BlcmF0aW9uVHlwZSxcbiAgICAgICAgICAgICAgICBpZFRva2VuUmVzcG9uc2VcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IGF1dGguX3VwZGF0ZUN1cnJlbnRVc2VyKHVzZXJDcmVkZW50aWFsLnVzZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHVzZXJDcmVkZW50aWFsO1xuICAgICAgICAgIGNhc2UgT3BlcmF0aW9uVHlwZS5SRUFVVEhFTlRJQ0FURTpcbiAgICAgICAgICAgIF9hc3NlcnQoZXJyb3IudXNlciwgYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgICAgICAgICByZXR1cm4gVXNlckNyZWRlbnRpYWxJbXBsLl9mb3JPcGVyYXRpb24oXG4gICAgICAgICAgICAgIGVycm9yLnVzZXIsXG4gICAgICAgICAgICAgIGVycm9yLm9wZXJhdGlvblR5cGUsXG4gICAgICAgICAgICAgIGlkVG9rZW5SZXNwb25zZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgX2ZhaWwoYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgYXN5bmMgcmVzb2x2ZVNpZ25JbihcbiAgICBhc3NlcnRpb25FeHRlcm46IE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbFxuICApOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gICAgY29uc3QgYXNzZXJ0aW9uID0gYXNzZXJ0aW9uRXh0ZXJuIGFzIE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbDtcbiAgICByZXR1cm4gdGhpcy5zaWduSW5SZXNvbHZlcihhc3NlcnRpb24pO1xuICB9XG59XG5cbi8qKlxuICogUHJvdmlkZXMgYSB7QGxpbmsgTXVsdGlGYWN0b3JSZXNvbHZlcn0gc3VpdGFibGUgZm9yIGNvbXBsZXRpb24gb2YgYVxuICogbXVsdGktZmFjdG9yIGZsb3cuXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVycm9yIC0gVGhlIHtAbGluayBNdWx0aUZhY3RvckVycm9yfSByYWlzZWQgZHVyaW5nIGEgc2lnbi1pbiwgb3JcbiAqIHJlYXV0aGVudGljYXRpb24gb3BlcmF0aW9uLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE11bHRpRmFjdG9yUmVzb2x2ZXIoXG4gIGF1dGg6IEF1dGgsXG4gIGVycm9yOiBNdWx0aUZhY3RvckVycm9yXG4pOiBNdWx0aUZhY3RvclJlc29sdmVyIHtcbiAgY29uc3QgYXV0aE1vZHVsYXIgPSBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCk7XG4gIGNvbnN0IGVycm9ySW50ZXJuYWwgPSBlcnJvciBhcyBNdWx0aUZhY3RvckVycm9ySW50ZXJuYWw7XG4gIF9hc3NlcnQoXG4gICAgZXJyb3IuY3VzdG9tRGF0YS5vcGVyYXRpb25UeXBlLFxuICAgIGF1dGhNb2R1bGFyLFxuICAgIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JcbiAgKTtcbiAgX2Fzc2VydChcbiAgICBlcnJvckludGVybmFsLmN1c3RvbURhdGEuX3NlcnZlclJlc3BvbnNlPy5tZmFQZW5kaW5nQ3JlZGVudGlhbCxcbiAgICBhdXRoTW9kdWxhcixcbiAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICk7XG5cbiAgcmV0dXJuIE11bHRpRmFjdG9yUmVzb2x2ZXJJbXBsLl9mcm9tRXJyb3IoYXV0aE1vZHVsYXIsIGVycm9ySW50ZXJuYWwpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEVuZHBvaW50LFxuICBIdHRwTWV0aG9kLFxuICBSZWNhcHRjaGFDbGllbnRUeXBlLFxuICBSZWNhcHRjaGFWZXJzaW9uLFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIF9wZXJmb3JtQXBpUmVxdWVzdFxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IH0gZnJvbSAnLi4vYXV0aGVudGljYXRpb24vc21zJztcbmltcG9ydCB7IEZpbmFsaXplTWZhUmVzcG9uc2UgfSBmcm9tICcuLi9hdXRoZW50aWNhdGlvbi9tZmEnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5cbi8qKlxuICogTUZBIEluZm8gYXMgcmV0dXJuZWQgYnkgdGhlIEFQSS5cbiAqL1xuaW50ZXJmYWNlIEJhc2VNZmFFbnJvbGxtZW50IHtcbiAgbWZhRW5yb2xsbWVudElkOiBzdHJpbmc7XG4gIGVucm9sbGVkQXQ6IG51bWJlcjtcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQW4gTUZBIHByb3ZpZGVkIGJ5IFNNUyB2ZXJpZmljYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGhvbmVNZmFFbnJvbGxtZW50IGV4dGVuZHMgQmFzZU1mYUVucm9sbG1lbnQge1xuICBwaG9uZUluZm86IHN0cmluZztcbn1cblxuLyoqXG4gKiBBbiBNRkEgcHJvdmlkZWQgYnkgVE9UUCAoVGltZS1iYXNlZCBPbmUgVGltZSBQYXNzd29yZCkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVG90cE1mYUVucm9sbG1lbnQgZXh0ZW5kcyBCYXNlTWZhRW5yb2xsbWVudCB7fVxuXG4vKipcbiAqIE1mYUVucm9sbG1lbnQgY2FuIGJlIGFueSBzdWJ0eXBlIG9mIEJhc2VNZmFFbnJvbGxtZW50LCBjdXJyZW50bHkgb25seSBQaG9uZU1mYUVucm9sbG1lbnQgYW5kIFRvdHBNZmFFbnJvbGxtZW50IGFyZSBzdXBwb3J0ZWQuXG4gKi9cbmV4cG9ydCB0eXBlIE1mYUVucm9sbG1lbnQgPSBQaG9uZU1mYUVucm9sbG1lbnQgfCBUb3RwTWZhRW5yb2xsbWVudDtcblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFBob25lTWZhRW5yb2xsbWVudFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHBob25lRW5yb2xsbWVudEluZm86IHtcbiAgICBwaG9uZU51bWJlcjogc3RyaW5nO1xuICAgIC8vIHJlQ0FQVENIQSB2MiB0b2tlblxuICAgIHJlY2FwdGNoYVRva2VuPzogc3RyaW5nO1xuICAgIC8vIHJlQ0FQVENIQSBFbnRlcnByaXNlIHRva2VuXG4gICAgY2FwdGNoYVJlc3BvbnNlPzogc3RyaW5nO1xuICAgIGNsaWVudFR5cGU/OiBSZWNhcHRjaGFDbGllbnRUeXBlO1xuICAgIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xuICB9O1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlIHtcbiAgcGhvbmVTZXNzaW9uSW5mbzoge1xuICAgIHNlc3Npb25JbmZvOiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydEVucm9sbFBob25lTWZhKFxuICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFN0YXJ0UGhvbmVNZmFFbnJvbGxtZW50UmVxdWVzdFxuKTogUHJvbWlzZTxTdGFydFBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgU3RhcnRQaG9uZU1mYUVucm9sbG1lbnRSZXF1ZXN0LFxuICAgIFN0YXJ0UGhvbmVNZmFFbnJvbGxtZW50UmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TVEFSVF9NRkFfRU5ST0xMTUVOVCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHBob25lVmVyaWZpY2F0aW9uSW5mbzogU2lnbkluV2l0aFBob25lTnVtYmVyUmVxdWVzdDtcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmcgfCBudWxsO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlXG4gIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgZnVuY3Rpb24gZmluYWxpemVFbnJvbGxQaG9uZU1mYShcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICByZXF1ZXN0OiBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlcXVlc3Rcbik6IFByb21pc2U8RmluYWxpemVQaG9uZU1mYUVucm9sbG1lbnRSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIEZpbmFsaXplUGhvbmVNZmFFbnJvbGxtZW50UmVxdWVzdCxcbiAgICBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuRklOQUxJWkVfTUZBX0VOUk9MTE1FTlQsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXF1ZXN0IHtcbiAgaWRUb2tlbjogc3RyaW5nO1xuICB0b3RwRW5yb2xsbWVudEluZm86IHt9O1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2Uge1xuICB0b3RwU2Vzc2lvbkluZm86IHtcbiAgICBzaGFyZWRTZWNyZXRLZXk6IHN0cmluZztcbiAgICB2ZXJpZmljYXRpb25Db2RlTGVuZ3RoOiBudW1iZXI7XG4gICAgaGFzaGluZ0FsZ29yaXRobTogc3RyaW5nO1xuICAgIHBlcmlvZFNlYzogbnVtYmVyO1xuICAgIHNlc3Npb25JbmZvOiBzdHJpbmc7XG4gICAgZmluYWxpemVFbnJvbGxtZW50VGltZTogbnVtYmVyO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRFbnJvbGxUb3RwTWZhKFxuICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXF1ZXN0XG4pOiBQcm9taXNlPFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXF1ZXN0LFxuICAgIFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZVxuICA+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNUQVJUX01GQV9FTlJPTExNRU5ULFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRvdHBWZXJpZmljYXRpb25JbmZvIHtcbiAgc2Vzc2lvbkluZm86IHN0cmluZztcbiAgdmVyaWZpY2F0aW9uQ29kZTogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVxdWVzdCB7XG4gIGlkVG9rZW46IHN0cmluZztcbiAgdG90cFZlcmlmaWNhdGlvbkluZm86IFRvdHBWZXJpZmljYXRpb25JbmZvO1xuICBkaXNwbGF5TmFtZT86IHN0cmluZyB8IG51bGw7XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbmFsaXplVG90cE1mYUVucm9sbG1lbnRSZXNwb25zZVxuICBleHRlbmRzIEZpbmFsaXplTWZhUmVzcG9uc2Uge31cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmFsaXplRW5yb2xsVG90cE1mYShcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICByZXF1ZXN0OiBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVxdWVzdFxuKTogUHJvbWlzZTxGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxcbiAgICBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVxdWVzdCxcbiAgICBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5GSU5BTElaRV9NRkFfRU5ST0xMTUVOVCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXaXRoZHJhd01mYVJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIG1mYUVucm9sbG1lbnRJZDogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXaXRoZHJhd01mYVJlc3BvbnNlIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgZnVuY3Rpb24gd2l0aGRyYXdNZmEoXG4gIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgcmVxdWVzdDogV2l0aGRyYXdNZmFSZXF1ZXN0XG4pOiBQcm9taXNlPFdpdGhkcmF3TWZhUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxXaXRoZHJhd01mYVJlcXVlc3QsIFdpdGhkcmF3TWZhUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LldJVEhEUkFXX01GQSxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHtcbiAgTXVsdGlGYWN0b3JBc3NlcnRpb24sXG4gIE11bHRpRmFjdG9ySW5mbyxcbiAgTXVsdGlGYWN0b3JTZXNzaW9uLFxuICBNdWx0aUZhY3RvclVzZXIsXG4gIFVzZXJcbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgd2l0aGRyYXdNZmEgfSBmcm9tICcuLi9hcGkvYWNjb3VudF9tYW5hZ2VtZW50L21mYSc7XG5pbXBvcnQgeyBfbG9nb3V0SWZJbnZhbGlkYXRlZCB9IGZyb20gJy4uL2NvcmUvdXNlci9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwgfSBmcm9tICcuL21mYV9hc3NlcnRpb24nO1xuaW1wb3J0IHsgTXVsdGlGYWN0b3JJbmZvSW1wbCB9IGZyb20gJy4vbWZhX2luZm8nO1xuaW1wb3J0IHsgTXVsdGlGYWN0b3JTZXNzaW9uSW1wbCB9IGZyb20gJy4vbWZhX3Nlc3Npb24nO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5leHBvcnQgY2xhc3MgTXVsdGlGYWN0b3JVc2VySW1wbCBpbXBsZW1lbnRzIE11bHRpRmFjdG9yVXNlciB7XG4gIGVucm9sbGVkRmFjdG9yczogTXVsdGlGYWN0b3JJbmZvW10gPSBbXTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHVzZXI6IFVzZXJJbnRlcm5hbCkge1xuICAgIHVzZXIuX29uUmVsb2FkKHVzZXJJbmZvID0+IHtcbiAgICAgIGlmICh1c2VySW5mby5tZmFJbmZvKSB7XG4gICAgICAgIHRoaXMuZW5yb2xsZWRGYWN0b3JzID0gdXNlckluZm8ubWZhSW5mby5tYXAoZW5yb2xsbWVudCA9PlxuICAgICAgICAgIE11bHRpRmFjdG9ySW5mb0ltcGwuX2Zyb21TZXJ2ZXJSZXNwb25zZSh1c2VyLmF1dGgsIGVucm9sbG1lbnQpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgX2Zyb21Vc2VyKHVzZXI6IFVzZXJJbnRlcm5hbCk6IE11bHRpRmFjdG9yVXNlckltcGwge1xuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JVc2VySW1wbCh1c2VyKTtcbiAgfVxuXG4gIGFzeW5jIGdldFNlc3Npb24oKTogUHJvbWlzZTxNdWx0aUZhY3RvclNlc3Npb24+IHtcbiAgICByZXR1cm4gTXVsdGlGYWN0b3JTZXNzaW9uSW1wbC5fZnJvbUlkdG9rZW4oXG4gICAgICBhd2FpdCB0aGlzLnVzZXIuZ2V0SWRUb2tlbigpLFxuICAgICAgdGhpcy51c2VyXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGVucm9sbChcbiAgICBhc3NlcnRpb25FeHRlcm46IE11bHRpRmFjdG9yQXNzZXJ0aW9uLFxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhc3NlcnRpb24gPSBhc3NlcnRpb25FeHRlcm4gYXMgTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsO1xuICAgIGNvbnN0IHNlc3Npb24gPSAoYXdhaXQgdGhpcy5nZXRTZXNzaW9uKCkpIGFzIE11bHRpRmFjdG9yU2Vzc2lvbkltcGw7XG4gICAgY29uc3QgZmluYWxpemVNZmFSZXNwb25zZSA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgICAgdGhpcy51c2VyLFxuICAgICAgYXNzZXJ0aW9uLl9wcm9jZXNzKHRoaXMudXNlci5hdXRoLCBzZXNzaW9uLCBkaXNwbGF5TmFtZSlcbiAgICApO1xuICAgIC8vIE5ldyB0b2tlbnMgd2lsbCBiZSBpc3N1ZWQgYWZ0ZXIgZW5yb2xsbWVudCBvZiB0aGUgbmV3IHNlY29uZCBmYWN0b3JzLlxuICAgIC8vIFRoZXkgbmVlZCB0byBiZSB1cGRhdGVkIG9uIHRoZSB1c2VyLlxuICAgIGF3YWl0IHRoaXMudXNlci5fdXBkYXRlVG9rZW5zSWZOZWNlc3NhcnkoZmluYWxpemVNZmFSZXNwb25zZSk7XG4gICAgLy8gVGhlIHVzZXIgbmVlZHMgdG8gYmUgcmVsb2FkZWQgdG8gZ2V0IHRoZSBuZXcgbXVsdGktZmFjdG9yIGluZm9ybWF0aW9uXG4gICAgLy8gZnJvbSBzZXJ2ZXIuIFVTRVJfUkVMT0FERUQgZXZlbnQgd2lsbCBiZSB0cmlnZ2VyZWQgYW5kIGBlbnJvbGxlZEZhY3RvcnNgXG4gICAgLy8gd2lsbCBiZSB1cGRhdGVkLlxuICAgIHJldHVybiB0aGlzLnVzZXIucmVsb2FkKCk7XG4gIH1cblxuICBhc3luYyB1bmVucm9sbChpbmZvT3JVaWQ6IE11bHRpRmFjdG9ySW5mbyB8IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1mYUVucm9sbG1lbnRJZCA9XG4gICAgICB0eXBlb2YgaW5mb09yVWlkID09PSAnc3RyaW5nJyA/IGluZm9PclVpZCA6IGluZm9PclVpZC51aWQ7XG4gICAgY29uc3QgaWRUb2tlbiA9IGF3YWl0IHRoaXMudXNlci5nZXRJZFRva2VuKCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGlkVG9rZW5SZXNwb25zZSA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgICAgICB0aGlzLnVzZXIsXG4gICAgICAgIHdpdGhkcmF3TWZhKHRoaXMudXNlci5hdXRoLCB7XG4gICAgICAgICAgaWRUb2tlbixcbiAgICAgICAgICBtZmFFbnJvbGxtZW50SWRcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICAvLyBSZW1vdmUgdGhlIHNlY29uZCBmYWN0b3IgZnJvbSB0aGUgdXNlcidzIGxpc3QuXG4gICAgICB0aGlzLmVucm9sbGVkRmFjdG9ycyA9IHRoaXMuZW5yb2xsZWRGYWN0b3JzLmZpbHRlcihcbiAgICAgICAgKHsgdWlkIH0pID0+IHVpZCAhPT0gbWZhRW5yb2xsbWVudElkXG4gICAgICApO1xuICAgICAgLy8gRGVwZW5kaW5nIG9uIHdoZXRoZXIgdGhlIGJhY2tlbmQgZGVjaWRlZCB0byByZXZva2UgdGhlIHVzZXIncyBzZXNzaW9uLFxuICAgICAgLy8gdGhlIHRva2VuUmVzcG9uc2UgbWF5IGJlIGVtcHR5LiBJZiB0aGUgdG9rZW5zIHdlcmUgbm90IHVwZGF0ZWQgKGFuZCB0aGV5XG4gICAgICAvLyBhcmUgbm93IGludmFsaWQpLCByZWxvYWRpbmcgdGhlIHVzZXIgd2lsbCBkaXNjb3ZlciB0aGlzIGFuZCBpbnZhbGlkYXRlXG4gICAgICAvLyB0aGUgdXNlcidzIHN0YXRlIGFjY29yZGluZ2x5LlxuICAgICAgYXdhaXQgdGhpcy51c2VyLl91cGRhdGVUb2tlbnNJZk5lY2Vzc2FyeShpZFRva2VuUmVzcG9uc2UpO1xuICAgICAgYXdhaXQgdGhpcy51c2VyLnJlbG9hZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IG11bHRpRmFjdG9yVXNlckNhY2hlID0gbmV3IFdlYWtNYXA8VXNlciwgTXVsdGlGYWN0b3JVc2VyPigpO1xuXG4vKipcbiAqIFRoZSB7QGxpbmsgTXVsdGlGYWN0b3JVc2VyfSBjb3JyZXNwb25kaW5nIHRvIHRoZSB1c2VyLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGlzIHVzZWQgdG8gYWNjZXNzIGFsbCBtdWx0aS1mYWN0b3IgcHJvcGVydGllcyBhbmQgb3BlcmF0aW9ucyByZWxhdGVkIHRvIHRoZSB1c2VyLlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlGYWN0b3IodXNlcjogVXNlcik6IE11bHRpRmFjdG9yVXNlciB7XG4gIGNvbnN0IHVzZXJNb2R1bGFyID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpO1xuICBpZiAoIW11bHRpRmFjdG9yVXNlckNhY2hlLmhhcyh1c2VyTW9kdWxhcikpIHtcbiAgICBtdWx0aUZhY3RvclVzZXJDYWNoZS5zZXQoXG4gICAgICB1c2VyTW9kdWxhcixcbiAgICAgIE11bHRpRmFjdG9yVXNlckltcGwuX2Zyb21Vc2VyKHVzZXJNb2R1bGFyIGFzIFVzZXJJbnRlcm5hbClcbiAgICApO1xuICB9XG4gIHJldHVybiBtdWx0aUZhY3RvclVzZXJDYWNoZS5nZXQodXNlck1vZHVsYXIpITtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVbnN1YnNjcmliZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEZpcmViYXNlQXV0aEludGVybmFsIH0gZnJvbSAnQGZpcmViYXNlL2F1dGgtaW50ZXJvcC10eXBlcyc7XG5cbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBfYXNzZXJ0IH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbmludGVyZmFjZSBUb2tlbkxpc3RlbmVyIHtcbiAgKHRvazogc3RyaW5nIHwgbnVsbCk6IHVua25vd247XG59XG5cbmV4cG9ydCBjbGFzcyBBdXRoSW50ZXJvcCBpbXBsZW1lbnRzIEZpcmViYXNlQXV0aEludGVybmFsIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcm5hbExpc3RlbmVyczogTWFwPFRva2VuTGlzdGVuZXIsIFVuc3Vic2NyaWJlPiA9XG4gICAgbmV3IE1hcCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgYXV0aDogQXV0aEludGVybmFsKSB7fVxuXG4gIGdldFVpZCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICB0aGlzLmFzc2VydEF1dGhDb25maWd1cmVkKCk7XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5jdXJyZW50VXNlcj8udWlkIHx8IG51bGw7XG4gIH1cblxuICBhc3luYyBnZXRUb2tlbihcbiAgICBmb3JjZVJlZnJlc2g/OiBib29sZWFuXG4gICk6IFByb21pc2U8eyBhY2Nlc3NUb2tlbjogc3RyaW5nIH0gfCBudWxsPiB7XG4gICAgdGhpcy5hc3NlcnRBdXRoQ29uZmlndXJlZCgpO1xuICAgIGF3YWl0IHRoaXMuYXV0aC5faW5pdGlhbGl6YXRpb25Qcm9taXNlO1xuICAgIGlmICghdGhpcy5hdXRoLmN1cnJlbnRVc2VyKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IGF3YWl0IHRoaXMuYXV0aC5jdXJyZW50VXNlci5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG4gICAgcmV0dXJuIHsgYWNjZXNzVG9rZW4gfTtcbiAgfVxuXG4gIGFkZEF1dGhUb2tlbkxpc3RlbmVyKGxpc3RlbmVyOiBUb2tlbkxpc3RlbmVyKTogdm9pZCB7XG4gICAgdGhpcy5hc3NlcnRBdXRoQ29uZmlndXJlZCgpO1xuICAgIGlmICh0aGlzLmludGVybmFsTGlzdGVuZXJzLmhhcyhsaXN0ZW5lcikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1bnN1YnNjcmliZSA9IHRoaXMuYXV0aC5vbklkVG9rZW5DaGFuZ2VkKHVzZXIgPT4ge1xuICAgICAgbGlzdGVuZXIoXG4gICAgICAgICh1c2VyIGFzIFVzZXJJbnRlcm5hbCB8IG51bGwpPy5zdHNUb2tlbk1hbmFnZXIuYWNjZXNzVG9rZW4gfHwgbnVsbFxuICAgICAgKTtcbiAgICB9KTtcbiAgICB0aGlzLmludGVybmFsTGlzdGVuZXJzLnNldChsaXN0ZW5lciwgdW5zdWJzY3JpYmUpO1xuICAgIHRoaXMudXBkYXRlUHJvYWN0aXZlUmVmcmVzaCgpO1xuICB9XG5cbiAgcmVtb3ZlQXV0aFRva2VuTGlzdGVuZXIobGlzdGVuZXI6IFRva2VuTGlzdGVuZXIpOiB2b2lkIHtcbiAgICB0aGlzLmFzc2VydEF1dGhDb25maWd1cmVkKCk7XG4gICAgY29uc3QgdW5zdWJzY3JpYmUgPSB0aGlzLmludGVybmFsTGlzdGVuZXJzLmdldChsaXN0ZW5lcik7XG4gICAgaWYgKCF1bnN1YnNjcmliZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuaW50ZXJuYWxMaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICB1bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudXBkYXRlUHJvYWN0aXZlUmVmcmVzaCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnRBdXRoQ29uZmlndXJlZCgpOiB2b2lkIHtcbiAgICBfYXNzZXJ0KFxuICAgICAgdGhpcy5hdXRoLl9pbml0aWFsaXphdGlvblByb21pc2UsXG4gICAgICBBdXRoRXJyb3JDb2RlLkRFUEVOREVOVF9TREtfSU5JVF9CRUZPUkVfQVVUSFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVByb2FjdGl2ZVJlZnJlc2goKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW50ZXJuYWxMaXN0ZW5lcnMuc2l6ZSA+IDApIHtcbiAgICAgIHRoaXMuYXV0aC5fc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXV0aC5fc3RvcFByb2FjdGl2ZVJlZnJlc2goKTtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBfcmVnaXN0ZXJDb21wb25lbnQsIHJlZ2lzdGVyVmVyc2lvbiB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRUeXBlLFxuICBJbnN0YW50aWF0aW9uTW9kZVxufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcblxuaW1wb3J0IHsgbmFtZSwgdmVyc2lvbiB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfZ2V0Q2xpZW50VmVyc2lvbiwgQ2xpZW50UGxhdGZvcm0gfSBmcm9tICcuLi91dGlsL3ZlcnNpb24nO1xuaW1wb3J0IHsgX2Nhc3RBdXRoLCBBdXRoSW1wbCwgRGVmYXVsdENvbmZpZyB9IGZyb20gJy4vYXV0aF9pbXBsJztcbmltcG9ydCB7IEF1dGhJbnRlcm9wIH0gZnJvbSAnLi9maXJlYmFzZV9pbnRlcm5hbCc7XG5pbXBvcnQgeyBDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgRGVwZW5kZW5jaWVzIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IF9pbml0aWFsaXplQXV0aEluc3RhbmNlIH0gZnJvbSAnLi9pbml0aWFsaXplJztcblxuZXhwb3J0IGNvbnN0IGVudW0gX0NvbXBvbmVudE5hbWUge1xuICBBVVRIID0gJ2F1dGgnLFxuICBBVVRIX0lOVEVSTkFMID0gJ2F1dGgtaW50ZXJuYWwnXG59XG5cbmZ1bmN0aW9uIGdldFZlcnNpb25Gb3JQbGF0Zm9ybShcbiAgY2xpZW50UGxhdGZvcm06IENsaWVudFBsYXRmb3JtXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBzd2l0Y2ggKGNsaWVudFBsYXRmb3JtKSB7XG4gICAgY2FzZSBDbGllbnRQbGF0Zm9ybS5OT0RFOlxuICAgICAgcmV0dXJuICdub2RlJztcbiAgICBjYXNlIENsaWVudFBsYXRmb3JtLlJFQUNUX05BVElWRTpcbiAgICAgIHJldHVybiAncm4nO1xuICAgIGNhc2UgQ2xpZW50UGxhdGZvcm0uV09SS0VSOlxuICAgICAgcmV0dXJuICd3ZWJ3b3JrZXInO1xuICAgIGNhc2UgQ2xpZW50UGxhdGZvcm0uQ09SRE9WQTpcbiAgICAgIHJldHVybiAnY29yZG92YSc7XG4gICAgY2FzZSBDbGllbnRQbGF0Zm9ybS5XRUJfRVhURU5TSU9OOlxuICAgICAgcmV0dXJuICd3ZWItZXh0ZW5zaW9uJztcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKiogQGludGVybmFsICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJBdXRoKGNsaWVudFBsYXRmb3JtOiBDbGllbnRQbGF0Zm9ybSk6IHZvaWQge1xuICBfcmVnaXN0ZXJDb21wb25lbnQoXG4gICAgbmV3IENvbXBvbmVudChcbiAgICAgIF9Db21wb25lbnROYW1lLkFVVEgsXG4gICAgICAoY29udGFpbmVyLCB7IG9wdGlvbnM6IGRlcHMgfTogeyBvcHRpb25zPzogRGVwZW5kZW5jaWVzIH0pID0+IHtcbiAgICAgICAgY29uc3QgYXBwID0gY29udGFpbmVyLmdldFByb3ZpZGVyKCdhcHAnKS5nZXRJbW1lZGlhdGUoKSE7XG4gICAgICAgIGNvbnN0IGhlYXJ0YmVhdFNlcnZpY2VQcm92aWRlciA9XG4gICAgICAgICAgY29udGFpbmVyLmdldFByb3ZpZGVyPCdoZWFydGJlYXQnPignaGVhcnRiZWF0Jyk7XG4gICAgICAgIGNvbnN0IGFwcENoZWNrU2VydmljZVByb3ZpZGVyID1cbiAgICAgICAgICBjb250YWluZXIuZ2V0UHJvdmlkZXI8J2FwcC1jaGVjay1pbnRlcm5hbCc+KCdhcHAtY2hlY2staW50ZXJuYWwnKTtcbiAgICAgICAgY29uc3QgeyBhcGlLZXksIGF1dGhEb21haW4gfSA9IGFwcC5vcHRpb25zO1xuXG4gICAgICAgIF9hc3NlcnQoXG4gICAgICAgICAgYXBpS2V5ICYmICFhcGlLZXkuaW5jbHVkZXMoJzonKSxcbiAgICAgICAgICBBdXRoRXJyb3JDb2RlLklOVkFMSURfQVBJX0tFWSxcbiAgICAgICAgICB7IGFwcE5hbWU6IGFwcC5uYW1lIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBjb25maWc6IENvbmZpZ0ludGVybmFsID0ge1xuICAgICAgICAgIGFwaUtleSxcbiAgICAgICAgICBhdXRoRG9tYWluLFxuICAgICAgICAgIGNsaWVudFBsYXRmb3JtLFxuICAgICAgICAgIGFwaUhvc3Q6IERlZmF1bHRDb25maWcuQVBJX0hPU1QsXG4gICAgICAgICAgdG9rZW5BcGlIb3N0OiBEZWZhdWx0Q29uZmlnLlRPS0VOX0FQSV9IT1NULFxuICAgICAgICAgIGFwaVNjaGVtZTogRGVmYXVsdENvbmZpZy5BUElfU0NIRU1FLFxuICAgICAgICAgIHNka0NsaWVudFZlcnNpb246IF9nZXRDbGllbnRWZXJzaW9uKGNsaWVudFBsYXRmb3JtKVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGF1dGhJbnN0YW5jZSA9IG5ldyBBdXRoSW1wbChcbiAgICAgICAgICBhcHAsXG4gICAgICAgICAgaGVhcnRiZWF0U2VydmljZVByb3ZpZGVyLFxuICAgICAgICAgIGFwcENoZWNrU2VydmljZVByb3ZpZGVyLFxuICAgICAgICAgIGNvbmZpZ1xuICAgICAgICApO1xuICAgICAgICBfaW5pdGlhbGl6ZUF1dGhJbnN0YW5jZShhdXRoSW5zdGFuY2UsIGRlcHMpO1xuXG4gICAgICAgIHJldHVybiBhdXRoSW5zdGFuY2U7XG4gICAgICB9LFxuICAgICAgQ29tcG9uZW50VHlwZS5QVUJMSUNcbiAgICApXG4gICAgICAvKipcbiAgICAgICAqIEF1dGggY2FuIG9ubHkgYmUgaW5pdGlhbGl6ZWQgYnkgZXhwbGljaXRseSBjYWxsaW5nIGdldEF1dGgoKSBvciBpbml0aWFsaXplQXV0aCgpXG4gICAgICAgKiBGb3Igd2h5IHdlIGRvIHRoaXMsIFNlZSBnby9maXJlYmFzZS1uZXh0LWF1dGgtaW5pdFxuICAgICAgICovXG4gICAgICAuc2V0SW5zdGFudGlhdGlvbk1vZGUoSW5zdGFudGlhdGlvbk1vZGUuRVhQTElDSVQpXG4gICAgICAvKipcbiAgICAgICAqIEJlY2F1c2UgYWxsIGZpcmViYXNlIHByb2R1Y3RzIHRoYXQgZGVwZW5kIG9uIGF1dGggZGVwZW5kIG9uIGF1dGgtaW50ZXJuYWwgZGlyZWN0bHksXG4gICAgICAgKiB3ZSBuZWVkIHRvIGluaXRpYWxpemUgYXV0aC1pbnRlcm5hbCBhZnRlciBhdXRoIGlzIGluaXRpYWxpemVkIHRvIG1ha2UgaXQgYXZhaWxhYmxlIHRvIG90aGVyIGZpcmViYXNlIHByb2R1Y3RzLlxuICAgICAgICovXG4gICAgICAuc2V0SW5zdGFuY2VDcmVhdGVkQ2FsbGJhY2soXG4gICAgICAgIChjb250YWluZXIsIF9pbnN0YW5jZUlkZW50aWZpZXIsIF9pbnN0YW5jZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGF1dGhJbnRlcm5hbFByb3ZpZGVyID0gY29udGFpbmVyLmdldFByb3ZpZGVyKFxuICAgICAgICAgICAgX0NvbXBvbmVudE5hbWUuQVVUSF9JTlRFUk5BTFxuICAgICAgICAgICk7XG4gICAgICAgICAgYXV0aEludGVybmFsUHJvdmlkZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgICB9XG4gICAgICApXG4gICk7XG5cbiAgX3JlZ2lzdGVyQ29tcG9uZW50KFxuICAgIG5ldyBDb21wb25lbnQoXG4gICAgICBfQ29tcG9uZW50TmFtZS5BVVRIX0lOVEVSTkFMLFxuICAgICAgY29udGFpbmVyID0+IHtcbiAgICAgICAgY29uc3QgYXV0aCA9IF9jYXN0QXV0aChcbiAgICAgICAgICBjb250YWluZXIuZ2V0UHJvdmlkZXIoX0NvbXBvbmVudE5hbWUuQVVUSCkuZ2V0SW1tZWRpYXRlKCkhXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiAoYXV0aCA9PiBuZXcgQXV0aEludGVyb3AoYXV0aCkpKGF1dGgpO1xuICAgICAgfSxcbiAgICAgIENvbXBvbmVudFR5cGUuUFJJVkFURVxuICAgICkuc2V0SW5zdGFudGlhdGlvbk1vZGUoSW5zdGFudGlhdGlvbk1vZGUuRVhQTElDSVQpXG4gICk7XG5cbiAgcmVnaXN0ZXJWZXJzaW9uKG5hbWUsIHZlcnNpb24sIGdldFZlcnNpb25Gb3JQbGF0Zm9ybShjbGllbnRQbGF0Zm9ybSkpO1xuICAvLyBCVUlMRF9UQVJHRVQgd2lsbCBiZSByZXBsYWNlZCBieSB2YWx1ZXMgbGlrZSBlc20sIGNqcywgZXRjIGR1cmluZyB0aGUgY29tcGlsYXRpb25cbiAgcmVnaXN0ZXJWZXJzaW9uKG5hbWUsIHZlcnNpb24sICdfX0JVSUxEX1RBUkdFVF9fJyk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2NvcmUvZXJyb3JzJztcbmltcG9ydCB7IF9jcmVhdGVFcnJvciB9IGZyb20gJy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuXG5pbXBvcnQgeyBGaXJlYmFzZUFwcCwgZ2V0QXBwLCBfZ2V0UHJvdmlkZXIgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IEF1dGggfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQgeyBpbml0aWFsaXplQXV0aCwgaW5NZW1vcnlQZXJzaXN0ZW5jZSwgY29ubmVjdEF1dGhFbXVsYXRvciB9IGZyb20gJy4uJztcbmltcG9ydCB7IHJlZ2lzdGVyQXV0aCB9IGZyb20gJy4uL2NvcmUvYXV0aC9yZWdpc3Rlcic7XG5pbXBvcnQgeyBDbGllbnRQbGF0Zm9ybSB9IGZyb20gJy4uL2NvcmUvdXRpbC92ZXJzaW9uJztcbmltcG9ydCB7IEF1dGhJbXBsIH0gZnJvbSAnLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5cbmltcG9ydCB7IEZldGNoUHJvdmlkZXIgfSBmcm9tICcuLi9jb3JlL3V0aWwvZmV0Y2hfcHJvdmlkZXInO1xuaW1wb3J0IHsgZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuLy8gSW5pdGlhbGl6ZSB0aGUgZmV0Y2ggcG9seWZpbGwsIHRoZSB0eXBlcyBhcmUgc2xpZ2h0bHkgb2ZmIHNvIGp1c3QgY2FzdCBhbmQgaG9wZSBmb3IgdGhlIGJlc3RcbkZldGNoUHJvdmlkZXIuaW5pdGlhbGl6ZShmZXRjaCwgSGVhZGVycywgUmVzcG9uc2UpO1xuXG4vLyBGaXJzdCwgd2Ugc2V0IHVwIHRoZSB2YXJpb3VzIHBsYXRmb3JtLXNwZWNpZmljIGZlYXR1cmVzIGZvciBOb2RlIChyZWdpc3RlclxuLy8gdGhlIHZlcnNpb24gYW5kIGRlY2xhcmUgdGhlIE5vZGUgZ2V0QXV0aCBmdW5jdGlvbilcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEF1dGgoYXBwOiBGaXJlYmFzZUFwcCA9IGdldEFwcCgpKTogQXV0aCB7XG4gIGNvbnN0IHByb3ZpZGVyID0gX2dldFByb3ZpZGVyKGFwcCwgJ2F1dGgnKTtcblxuICBpZiAocHJvdmlkZXIuaXNJbml0aWFsaXplZCgpKSB7XG4gICAgcmV0dXJuIHByb3ZpZGVyLmdldEltbWVkaWF0ZSgpO1xuICB9XG5cbiAgY29uc3QgYXV0aCA9IGluaXRpYWxpemVBdXRoKGFwcCk7XG5cbiAgY29uc3QgYXV0aEVtdWxhdG9ySG9zdCA9IGdldERlZmF1bHRFbXVsYXRvckhvc3QoJ2F1dGgnKTtcbiAgaWYgKGF1dGhFbXVsYXRvckhvc3QpIHtcbiAgICBjb25uZWN0QXV0aEVtdWxhdG9yKGF1dGgsIGBodHRwOi8vJHthdXRoRW11bGF0b3JIb3N0fWApO1xuICB9XG5cbiAgcmV0dXJuIGF1dGg7XG59XG5cbnJlZ2lzdGVyQXV0aChDbGllbnRQbGF0Zm9ybS5OT0RFKTtcblxuLy8gVGhlIHJlc3Qgb2YgdGhpcyBmaWxlIGNvbnRhaW5zIG5vLW9wcyBhbmQgZXJyb3JzIGZvciBicm93c2VyLXNwZWNpZmljXG4vLyBtZXRob2RzLiBXZSBrZWVwIHRoZSBicm93c2VyIGFuZCBOb2RlIGVudHJ5IHBvaW50cyB0aGUgc2FtZSwgYnV0IGZlYXR1cmVzXG4vLyB0aGF0IG9ubHkgd29yayBpbiBicm93c2VycyBhcmUgc2V0IHRvIGVpdGhlciBkbyBub3RoaW5nIChzZXRQZXJzaXN0ZW5jZSkgb3Jcbi8vIHRvIHJlamVjdCB3aXRoIGFuIGF1dGgvb3BlcmF0aW9uLW5vdC1zdXBwb3J0ZWQtaW4tdGhpcy1lbnZpcm9ubWVudCBlcnJvci5cbi8vIFRoZSBiZWxvdyBleHBvcnRzIGFyZSBwdWxsZWQgaW50byB0aGUgbWFpbiBlbnRyeSBwb2ludCBieSBhIHJvbGx1cCBhbGlhc1xuLy8gcGx1Z2luIChvdmVyd3JpdGluZyB0aGUgZGVmYXVsdCBicm93c2VyIGltcG9ydHMpLlxuXG4vKiogYXV0aC9vcGVyYXRpb24tbm90LXN1cHBvcnRlZC1pbi10aGlzLWVudmlyb25tZW50ICovXG5jb25zdCBOT1RfQVZBSUxBQkxFX0VSUk9SID0gX2NyZWF0ZUVycm9yKEF1dGhFcnJvckNvZGUuT1BFUkFUSU9OX05PVF9TVVBQT1JURUQpO1xuXG4vKiogUmVqZWN0IHdpdGggYXV0aC9vcGVyYXRpb24tbm90LXN1cHBvcnRlZC1pbi10aGlzLWVudmlyb25tZW50ICovXG5hc3luYyBmdW5jdGlvbiBmYWlsKCk6IFByb21pc2U8dm9pZD4ge1xuICB0aHJvdyBOT1RfQVZBSUxBQkxFX0VSUk9SO1xufVxuXG4vKipcbiAqIEEgY2xhc3Mgd2hpY2ggd2lsbCB0aHJvdyB3aXRoXG4gKiBhdXRoL29wZXJhdGlvbi1ub3Qtc3VwcG9ydGVkLWluLXRoaXMtZW52aXJvbm1lbnQgaWYgaW5zdGFudGlhdGVkXG4gKi9cbmNsYXNzIEZhaWxDbGFzcyB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRocm93IE5PVF9BVkFJTEFCTEVfRVJST1I7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGJyb3dzZXJMb2NhbFBlcnNpc3RlbmNlID0gaW5NZW1vcnlQZXJzaXN0ZW5jZTtcbmV4cG9ydCBjb25zdCBicm93c2VyU2Vzc2lvblBlcnNpc3RlbmNlID0gaW5NZW1vcnlQZXJzaXN0ZW5jZTtcbmV4cG9ydCBjb25zdCBicm93c2VyQ29va2llUGVyc2lzdGVuY2UgPSBpbk1lbW9yeVBlcnNpc3RlbmNlO1xuZXhwb3J0IGNvbnN0IGluZGV4ZWREQkxvY2FsUGVyc2lzdGVuY2UgPSBpbk1lbW9yeVBlcnNpc3RlbmNlO1xuZXhwb3J0IGNvbnN0IGJyb3dzZXJQb3B1cFJlZGlyZWN0UmVzb2x2ZXIgPSBOT1RfQVZBSUxBQkxFX0VSUk9SO1xuZXhwb3J0IGNvbnN0IFBob25lQXV0aFByb3ZpZGVyID0gRmFpbENsYXNzO1xuZXhwb3J0IGNvbnN0IHNpZ25JbldpdGhQaG9uZU51bWJlciA9IGZhaWw7XG5leHBvcnQgY29uc3QgbGlua1dpdGhQaG9uZU51bWJlciA9IGZhaWw7XG5leHBvcnQgY29uc3QgcmVhdXRoZW50aWNhdGVXaXRoUGhvbmVOdW1iZXIgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IHVwZGF0ZVBob25lTnVtYmVyID0gZmFpbDtcbmV4cG9ydCBjb25zdCBzaWduSW5XaXRoUG9wdXAgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IGxpbmtXaXRoUG9wdXAgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IHJlYXV0aGVudGljYXRlV2l0aFBvcHVwID0gZmFpbDtcbmV4cG9ydCBjb25zdCBzaWduSW5XaXRoUmVkaXJlY3QgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IGxpbmtXaXRoUmVkaXJlY3QgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IHJlYXV0aGVudGljYXRlV2l0aFJlZGlyZWN0ID0gZmFpbDtcbmV4cG9ydCBjb25zdCBnZXRSZWRpcmVjdFJlc3VsdCA9IGZhaWw7XG5leHBvcnQgY29uc3QgUmVjYXB0Y2hhVmVyaWZpZXIgPSBGYWlsQ2xhc3M7XG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZyA9IGZhaWw7XG5leHBvcnQgY2xhc3MgUGhvbmVNdWx0aUZhY3RvckdlbmVyYXRvciB7XG4gIHN0YXRpYyBhc3NlcnRpb24oKTogdW5rbm93biB7XG4gICAgdGhyb3cgTk9UX0FWQUlMQUJMRV9FUlJPUjtcbiAgfVxufVxuXG4vLyBTZXQgcGVyc2lzdGVuY2Ugc2hvdWxkIG5vLW9wIGluc3RlYWQgb2YgZmFpbC4gQ2hhbmdpbmcgdGhlIHByb3RvdHlwZSB3aWxsXG4vLyBtYWtlIHN1cmUgYm90aCBzZXRQZXJzaXN0ZW5jZShhdXRoLCBwZXJzaXN0ZW5jZSkgYW5kXG4vLyBhdXRoLnNldFBlcnNpc3RlbmNlKHBlcnNpc3RlbmNlKSBhcmUgY292ZXJlZC5cbkF1dGhJbXBsLnByb3RvdHlwZS5zZXRQZXJzaXN0ZW5jZSA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHt9O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYVZlcnNpb24sXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeVxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IE1mYUVucm9sbG1lbnQgfSBmcm9tICcuLi9hY2NvdW50X21hbmFnZW1lbnQvbWZhJztcbmltcG9ydCB7IFNpZ25JbldpdGhJZHBSZXNwb25zZSB9IGZyb20gJy4vaWRwJztcbmltcG9ydCB7XG4gIFNpZ25JbldpdGhQaG9uZU51bWJlclJlcXVlc3QsXG4gIFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlXG59IGZyb20gJy4vc21zJztcblxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZU1mYVJlc3BvbnNlIHtcbiAgaWRUb2tlbjogc3RyaW5nO1xuICByZWZyZXNoVG9rZW46IHN0cmluZztcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJZFRva2VuTWZhUmVzcG9uc2UgZXh0ZW5kcyBJZFRva2VuUmVzcG9uc2Uge1xuICBtZmFQZW5kaW5nQ3JlZGVudGlhbD86IHN0cmluZztcbiAgbWZhSW5mbz86IE1mYUVucm9sbG1lbnRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFBob25lTWZhU2lnbkluUmVxdWVzdCB7XG4gIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmc7XG4gIG1mYUVucm9sbG1lbnRJZDogc3RyaW5nO1xuICBwaG9uZVNpZ25JbkluZm86IHtcbiAgICAvLyByZUNBUFRDSEEgdjIgdG9rZW5cbiAgICByZWNhcHRjaGFUb2tlbj86IHN0cmluZztcbiAgICAvLyByZUNBUFRDSEEgRW50ZXJwcmlzZSB0b2tlblxuICAgIGNhcHRjaGFSZXNwb25zZT86IHN0cmluZztcbiAgICBjbGllbnRUeXBlPzogUmVjYXB0Y2hhQ2xpZW50VHlwZTtcbiAgICByZWNhcHRjaGFWZXJzaW9uPzogUmVjYXB0Y2hhVmVyc2lvbjtcbiAgfTtcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhcnRQaG9uZU1mYVNpZ25JblJlc3BvbnNlIHtcbiAgcGhvbmVSZXNwb25zZUluZm86IHtcbiAgICBzZXNzaW9uSW5mbzogc3RyaW5nO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRTaWduSW5QaG9uZU1mYShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8U3RhcnRQaG9uZU1mYVNpZ25JblJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3QsXG4gICAgU3RhcnRQaG9uZU1mYVNpZ25JblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU1RBUlRfTUZBX1NJR05fSU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlcXVlc3Qge1xuICBtZmFQZW5kaW5nQ3JlZGVudGlhbDogc3RyaW5nO1xuICBwaG9uZVZlcmlmaWNhdGlvbkluZm86IFNpZ25JbldpdGhQaG9uZU51bWJlclJlcXVlc3Q7XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG4vLyBUT1RQIE1GQSBTaWduIGluIG9ubHkgaGFzIGEgZmluYWxpemUgcGhhc2UuIFBob25lIE1GQSBoYXMgYSBzdGFydCBwaGFzZSB0byBpbml0aWF0ZSBzZW5kaW5nIGFuXG4vLyBTTVMgYW5kIGEgZmluYWxpemUgcGhhc2UgdG8gY29tcGxldGUgc2lnbiBpbi4gV2l0aCBUT1RQLCB0aGUgdXNlciBhbHJlYWR5IGhhcyB0aGUgT1RQIGluIHRoZVxuLy8gVE9UUC9BdXRoZW50aWNhdG9yIGFwcC5cbmV4cG9ydCBpbnRlcmZhY2UgRmluYWxpemVUb3RwTWZhU2lnbkluUmVxdWVzdCB7XG4gIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmc7XG4gIHRvdHBWZXJpZmljYXRpb25JbmZvOiB7IHZlcmlmaWNhdGlvbkNvZGU6IHN0cmluZyB9O1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgbWZhRW5yb2xsbWVudElkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlc3BvbnNlIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbmFsaXplVG90cE1mYVNpZ25JblJlc3BvbnNlIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgZnVuY3Rpb24gZmluYWxpemVTaWduSW5QaG9uZU1mYShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogRmluYWxpemVQaG9uZU1mYVNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8RmluYWxpemVQaG9uZU1mYVNpZ25JblJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlcXVlc3QsXG4gICAgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuRklOQUxJWkVfTUZBX1NJR05fSU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5hbGl6ZVNpZ25JblRvdHBNZmEoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IEZpbmFsaXplVG90cE1mYVNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8RmluYWxpemVUb3RwTWZhU2lnbkluUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxcbiAgICBGaW5hbGl6ZVRvdHBNZmFTaWduSW5SZXF1ZXN0LFxuICAgIEZpbmFsaXplVG90cE1mYVNpZ25JblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuRklOQUxJWkVfTUZBX1NJR05fSU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCB0eXBlIFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2UgPVxuICB8IFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlXG4gIHwgU2lnbkluV2l0aElkcFJlc3BvbnNlXG4gIHwgSWRUb2tlblJlc3BvbnNlO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5pbXBvcnQgeyBGYWN0b3JJZCwgTXVsdGlGYWN0b3JBc3NlcnRpb24gfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgZGVidWdGYWlsIH0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBNdWx0aUZhY3RvclNlc3Npb25JbXBsLCBNdWx0aUZhY3RvclNlc3Npb25UeXBlIH0gZnJvbSAnLi9tZmFfc2Vzc2lvbic7XG5pbXBvcnQgeyBGaW5hbGl6ZU1mYVJlc3BvbnNlIH0gZnJvbSAnLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi9tb2RlbC9hdXRoJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbCBpbXBsZW1lbnRzIE11bHRpRmFjdG9yQXNzZXJ0aW9uIHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGZhY3RvcklkOiBGYWN0b3JJZCkge31cblxuICBfcHJvY2VzcyhcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgc2Vzc2lvbjogTXVsdGlGYWN0b3JTZXNzaW9uSW1wbCxcbiAgICBkaXNwbGF5TmFtZT86IHN0cmluZyB8IG51bGxcbiAgKTogUHJvbWlzZTxGaW5hbGl6ZU1mYVJlc3BvbnNlPiB7XG4gICAgc3dpdGNoIChzZXNzaW9uLnR5cGUpIHtcbiAgICAgIGNhc2UgTXVsdGlGYWN0b3JTZXNzaW9uVHlwZS5FTlJPTEw6XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5hbGl6ZUVucm9sbChhdXRoLCBzZXNzaW9uLmNyZWRlbnRpYWwsIGRpc3BsYXlOYW1lKTtcbiAgICAgIGNhc2UgTXVsdGlGYWN0b3JTZXNzaW9uVHlwZS5TSUdOX0lOOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluYWxpemVTaWduSW4oYXV0aCwgc2Vzc2lvbi5jcmVkZW50aWFsKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBkZWJ1Z0ZhaWwoJ3VuZXhwZWN0ZWQgTXVsdGlGYWN0b3JTZXNzaW9uVHlwZScpO1xuICAgIH1cbiAgfVxuXG4gIGFic3RyYWN0IF9maW5hbGl6ZUVucm9sbChcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgaWRUb2tlbjogc3RyaW5nLFxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbFxuICApOiBQcm9taXNlPEZpbmFsaXplTWZhUmVzcG9uc2U+O1xuICBhYnN0cmFjdCBfZmluYWxpemVTaWduSW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxGaW5hbGl6ZU1mYVJlc3BvbnNlPjtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHtcbiAgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uLFxuICBNdWx0aUZhY3RvclNlc3Npb24sXG4gIEZhY3RvcklkXG59IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7XG4gIGZpbmFsaXplRW5yb2xsVG90cE1mYSxcbiAgc3RhcnRFbnJvbGxUb3RwTWZhLFxuICBTdGFydFRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2UsXG4gIFRvdHBWZXJpZmljYXRpb25JbmZvXG59IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvbWZhJztcbmltcG9ydCB7XG4gIEZpbmFsaXplTWZhUmVzcG9uc2UsXG4gIGZpbmFsaXplU2lnbkluVG90cE1mYVxufSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbCB9IGZyb20gJy4uLy4uL21mYS9tZmFfYXNzZXJ0aW9uJztcbmltcG9ydCB7IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwgfSBmcm9tICcuLi9tZmFfc2Vzc2lvbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBnZW5lcmF0aW5nIGEge0BsaW5rIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbn0uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgVG90cE11bHRpRmFjdG9yR2VuZXJhdG9yIHtcbiAgLyoqXG4gICAqIFByb3ZpZGVzIGEge0BsaW5rIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbn0gdG8gY29uZmlybSBvd25lcnNoaXAgb2ZcbiAgICogdGhlIFRPVFAgKHRpbWUtYmFzZWQgb25lLXRpbWUgcGFzc3dvcmQpIHNlY29uZCBmYWN0b3IuXG4gICAqIFRoaXMgYXNzZXJ0aW9uIGlzIHVzZWQgdG8gY29tcGxldGUgZW5yb2xsbWVudCBpbiBUT1RQIHNlY29uZCBmYWN0b3IuXG4gICAqXG4gICAqIEBwYXJhbSBzZWNyZXQgQSB7QGxpbmsgVG90cFNlY3JldH0gY29udGFpbmluZyB0aGUgc2hhcmVkIHNlY3JldCBrZXkgYW5kIG90aGVyIFRPVFAgcGFyYW1ldGVycy5cbiAgICogQHBhcmFtIG9uZVRpbWVQYXNzd29yZCBPbmUtdGltZSBwYXNzd29yZCBmcm9tIFRPVFAgQXBwLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb259IHdoaWNoIGNhbiBiZSB1c2VkIHdpdGhcbiAgICoge0BsaW5rIE11bHRpRmFjdG9yVXNlci5lbnJvbGx9LlxuICAgKi9cbiAgc3RhdGljIGFzc2VydGlvbkZvckVucm9sbG1lbnQoXG4gICAgc2VjcmV0OiBUb3RwU2VjcmV0LFxuICAgIG9uZVRpbWVQYXNzd29yZDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbiB7XG4gICAgcmV0dXJuIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwuX2Zyb21TZWNyZXQoc2VjcmV0LCBvbmVUaW1lUGFzc3dvcmQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3ZpZGVzIGEge0BsaW5rIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbn0gdG8gY29uZmlybSBvd25lcnNoaXAgb2YgdGhlIFRPVFAgc2Vjb25kIGZhY3Rvci5cbiAgICogVGhpcyBhc3NlcnRpb24gaXMgdXNlZCB0byBjb21wbGV0ZSBzaWduSW4gd2l0aCBUT1RQIGFzIHRoZSBzZWNvbmQgZmFjdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gZW5yb2xsbWVudElkIGlkZW50aWZpZXMgdGhlIGVucm9sbGVkIFRPVFAgc2Vjb25kIGZhY3Rvci5cbiAgICogQHBhcmFtIG9uZVRpbWVQYXNzd29yZCBPbmUtdGltZSBwYXNzd29yZCBmcm9tIFRPVFAgQXBwLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb259IHdoaWNoIGNhbiBiZSB1c2VkIHdpdGhcbiAgICoge0BsaW5rIE11bHRpRmFjdG9yUmVzb2x2ZXIucmVzb2x2ZVNpZ25Jbn0uXG4gICAqL1xuICBzdGF0aWMgYXNzZXJ0aW9uRm9yU2lnbkluKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIG9uZVRpbWVQYXNzd29yZDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbiB7XG4gICAgcmV0dXJuIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwuX2Zyb21FbnJvbGxtZW50SWQoXG4gICAgICBlbnJvbGxtZW50SWQsXG4gICAgICBvbmVUaW1lUGFzc3dvcmRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBwcm9taXNlIHRvIHtAbGluayBUb3RwU2VjcmV0fSB3aGljaCBjb250YWlucyB0aGUgVE9UUCBzaGFyZWQgc2VjcmV0IGtleSBhbmQgb3RoZXIgcGFyYW1ldGVycy5cbiAgICogQ3JlYXRlcyBhIFRPVFAgc2VjcmV0IGFzIHBhcnQgb2YgZW5yb2xsaW5nIGEgVE9UUCBzZWNvbmQgZmFjdG9yLlxuICAgKiBVc2VkIGZvciBnZW5lcmF0aW5nIGEgUVIgY29kZSBVUkwgb3IgaW5wdXR0aW5nIGludG8gYSBUT1RQIGFwcC5cbiAgICogVGhpcyBtZXRob2QgdXNlcyB0aGUgYXV0aCBpbnN0YW5jZSBjb3JyZXNwb25kaW5nIHRvIHRoZSB1c2VyIGluIHRoZSBtdWx0aUZhY3RvclNlc3Npb24uXG4gICAqXG4gICAqIEBwYXJhbSBzZXNzaW9uIFRoZSB7QGxpbmsgTXVsdGlGYWN0b3JTZXNzaW9ufSB0aGF0IHRoZSB1c2VyIGlzIHBhcnQgb2YuXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0byB7QGxpbmsgVG90cFNlY3JldH0uXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2VuZXJhdGVTZWNyZXQoXG4gICAgc2Vzc2lvbjogTXVsdGlGYWN0b3JTZXNzaW9uXG4gICk6IFByb21pc2U8VG90cFNlY3JldD4ge1xuICAgIGNvbnN0IG1mYVNlc3Npb24gPSBzZXNzaW9uIGFzIE11bHRpRmFjdG9yU2Vzc2lvbkltcGw7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiBtZmFTZXNzaW9uLnVzZXI/LmF1dGggIT09ICd1bmRlZmluZWQnLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzdGFydEVucm9sbFRvdHBNZmEobWZhU2Vzc2lvbi51c2VyLmF1dGgsIHtcbiAgICAgIGlkVG9rZW46IG1mYVNlc3Npb24uY3JlZGVudGlhbCxcbiAgICAgIHRvdHBFbnJvbGxtZW50SW5mbzoge31cbiAgICB9KTtcbiAgICByZXR1cm4gVG90cFNlY3JldC5fZnJvbVN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZShcbiAgICAgIHJlc3BvbnNlLFxuICAgICAgbWZhU2Vzc2lvbi51c2VyLmF1dGhcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpZGVudGlmaWVyIG9mIHRoZSBUT1RQIHNlY29uZCBmYWN0b3I6IGB0b3RwYC5cbiAgICovXG4gIHN0YXRpYyBGQUNUT1JfSUQ6ICd0b3RwJyA9IEZhY3RvcklkLlRPVFA7XG59XG5cbmV4cG9ydCBjbGFzcyBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsXG4gIGV4dGVuZHMgTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsXG4gIGltcGxlbWVudHMgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uXG57XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IG90cDogc3RyaW5nLFxuICAgIHJlYWRvbmx5IGVucm9sbG1lbnRJZD86IHN0cmluZyxcbiAgICByZWFkb25seSBzZWNyZXQ/OiBUb3RwU2VjcmV0XG4gICkge1xuICAgIHN1cGVyKEZhY3RvcklkLlRPVFApO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX2Zyb21TZWNyZXQoXG4gICAgc2VjcmV0OiBUb3RwU2VjcmV0LFxuICAgIG90cDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwge1xuICAgIHJldHVybiBuZXcgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbChvdHAsIHVuZGVmaW5lZCwgc2VjcmV0KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tRW5yb2xsbWVudElkKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIG90cDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwge1xuICAgIHJldHVybiBuZXcgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbChvdHAsIGVucm9sbG1lbnRJZCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGFzeW5jIF9maW5hbGl6ZUVucm9sbChcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgaWRUb2tlbjogc3RyaW5nLFxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbFxuICApOiBQcm9taXNlPEZpbmFsaXplTWZhUmVzcG9uc2U+IHtcbiAgICBfYXNzZXJ0KFxuICAgICAgdHlwZW9mIHRoaXMuc2VjcmV0ICE9PSAndW5kZWZpbmVkJyxcbiAgICAgIGF1dGgsXG4gICAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICAgKTtcbiAgICByZXR1cm4gZmluYWxpemVFbnJvbGxUb3RwTWZhKGF1dGgsIHtcbiAgICAgIGlkVG9rZW4sXG4gICAgICBkaXNwbGF5TmFtZSxcbiAgICAgIHRvdHBWZXJpZmljYXRpb25JbmZvOiB0aGlzLnNlY3JldC5fbWFrZVRvdHBWZXJpZmljYXRpb25JbmZvKHRoaXMub3RwKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBhc3luYyBfZmluYWxpemVTaWduSW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxGaW5hbGl6ZU1mYVJlc3BvbnNlPiB7XG4gICAgX2Fzc2VydChcbiAgICAgIHRoaXMuZW5yb2xsbWVudElkICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vdHAgIT09IHVuZGVmaW5lZCxcbiAgICAgIGF1dGgsXG4gICAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICAgKTtcbiAgICBjb25zdCB0b3RwVmVyaWZpY2F0aW9uSW5mbyA9IHsgdmVyaWZpY2F0aW9uQ29kZTogdGhpcy5vdHAgfTtcbiAgICByZXR1cm4gZmluYWxpemVTaWduSW5Ub3RwTWZhKGF1dGgsIHtcbiAgICAgIG1mYVBlbmRpbmdDcmVkZW50aWFsLFxuICAgICAgbWZhRW5yb2xsbWVudElkOiB0aGlzLmVucm9sbG1lbnRJZCxcbiAgICAgIHRvdHBWZXJpZmljYXRpb25JbmZvXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBQcm92aWRlciBmb3IgZ2VuZXJhdGluZyBhIHtAbGluayBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb259LlxuICpcbiAqIFN0b3JlcyB0aGUgc2hhcmVkIHNlY3JldCBrZXkgYW5kIG90aGVyIHBhcmFtZXRlcnMgdG8gZ2VuZXJhdGUgdGltZS1iYXNlZCBPVFBzLlxuICogSW1wbGVtZW50cyBtZXRob2RzIHRvIHJldHJpZXZlIHRoZSBzaGFyZWQgc2VjcmV0IGtleSBhbmQgZ2VuZXJhdGUgYSBRUiBjb2RlIFVSTC5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFRvdHBTZWNyZXQge1xuICAvKipcbiAgICogU2hhcmVkIHNlY3JldCBrZXkvc2VlZCB1c2VkIGZvciBlbnJvbGxpbmcgaW4gVE9UUCBNRkEgYW5kIGdlbmVyYXRpbmcgT1RQcy5cbiAgICovXG4gIHJlYWRvbmx5IHNlY3JldEtleTogc3RyaW5nO1xuICAvKipcbiAgICogSGFzaGluZyBhbGdvcml0aG0gdXNlZC5cbiAgICovXG4gIHJlYWRvbmx5IGhhc2hpbmdBbGdvcml0aG06IHN0cmluZztcbiAgLyoqXG4gICAqIExlbmd0aCBvZiB0aGUgb25lLXRpbWUgcGFzc3dvcmRzIHRvIGJlIGdlbmVyYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGNvZGVMZW5ndGg6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBpbnRlcnZhbCAoaW4gc2Vjb25kcykgd2hlbiB0aGUgT1RQIGNvZGVzIHNob3VsZCBjaGFuZ2UuXG4gICAqL1xuICByZWFkb25seSBjb2RlSW50ZXJ2YWxTZWNvbmRzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgdGltZXN0YW1wIChVVEMgc3RyaW5nKSBieSB3aGljaCBUT1RQIGVucm9sbG1lbnQgc2hvdWxkIGJlIGNvbXBsZXRlZC5cbiAgICovXG4gIC8vIFRoaXMgY2FuIGJlIHVzZWQgYnkgY2FsbGVycyB0byBzaG93IGEgY291bnRkb3duIG9mIHdoZW4gdG8gZW50ZXIgT1RQIGNvZGUgYnkuXG4gIHJlYWRvbmx5IGVucm9sbG1lbnRDb21wbGV0aW9uRGVhZGxpbmU6IHN0cmluZztcblxuICAvLyBUaGUgcHVibGljIG1lbWJlcnMgYXJlIGRlY2xhcmVkIG91dHNpZGUgdGhlIGNvbnN0cnVjdG9yIHNvIHRoZSBkb2NzIGNhbiBiZSBnZW5lcmF0ZWQuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgc2VjcmV0S2V5OiBzdHJpbmcsXG4gICAgaGFzaGluZ0FsZ29yaXRobTogc3RyaW5nLFxuICAgIGNvZGVMZW5ndGg6IG51bWJlcixcbiAgICBjb2RlSW50ZXJ2YWxTZWNvbmRzOiBudW1iZXIsXG4gICAgZW5yb2xsbWVudENvbXBsZXRpb25EZWFkbGluZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2Vzc2lvbkluZm86IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbFxuICApIHtcbiAgICB0aGlzLnNlY3JldEtleSA9IHNlY3JldEtleTtcbiAgICB0aGlzLmhhc2hpbmdBbGdvcml0aG0gPSBoYXNoaW5nQWxnb3JpdGhtO1xuICAgIHRoaXMuY29kZUxlbmd0aCA9IGNvZGVMZW5ndGg7XG4gICAgdGhpcy5jb2RlSW50ZXJ2YWxTZWNvbmRzID0gY29kZUludGVydmFsU2Vjb25kcztcbiAgICB0aGlzLmVucm9sbG1lbnRDb21wbGV0aW9uRGVhZGxpbmUgPSBlbnJvbGxtZW50Q29tcGxldGlvbkRlYWRsaW5lO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX2Zyb21TdGFydFRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2UoXG4gICAgcmVzcG9uc2U6IFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZSxcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWxcbiAgKTogVG90cFNlY3JldCB7XG4gICAgcmV0dXJuIG5ldyBUb3RwU2VjcmV0KFxuICAgICAgcmVzcG9uc2UudG90cFNlc3Npb25JbmZvLnNoYXJlZFNlY3JldEtleSxcbiAgICAgIHJlc3BvbnNlLnRvdHBTZXNzaW9uSW5mby5oYXNoaW5nQWxnb3JpdGhtLFxuICAgICAgcmVzcG9uc2UudG90cFNlc3Npb25JbmZvLnZlcmlmaWNhdGlvbkNvZGVMZW5ndGgsXG4gICAgICByZXNwb25zZS50b3RwU2Vzc2lvbkluZm8ucGVyaW9kU2VjLFxuICAgICAgbmV3IERhdGUocmVzcG9uc2UudG90cFNlc3Npb25JbmZvLmZpbmFsaXplRW5yb2xsbWVudFRpbWUpLnRvVVRDU3RyaW5nKCksXG4gICAgICByZXNwb25zZS50b3RwU2Vzc2lvbkluZm8uc2Vzc2lvbkluZm8sXG4gICAgICBhdXRoXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX21ha2VUb3RwVmVyaWZpY2F0aW9uSW5mbyhvdHA6IHN0cmluZyk6IFRvdHBWZXJpZmljYXRpb25JbmZvIHtcbiAgICByZXR1cm4geyBzZXNzaW9uSW5mbzogdGhpcy5zZXNzaW9uSW5mbywgdmVyaWZpY2F0aW9uQ29kZTogb3RwIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIFFSIGNvZGUgVVJMIGFzIGRlc2NyaWJlZCBpblxuICAgKiBodHRwczovL2dpdGh1Yi5jb20vZ29vZ2xlL2dvb2dsZS1hdXRoZW50aWNhdG9yL3dpa2kvS2V5LVVyaS1Gb3JtYXRcbiAgICogVGhpcyBjYW4gYmUgZGlzcGxheWVkIHRvIHRoZSB1c2VyIGFzIGEgUVIgY29kZSB0byBiZSBzY2FubmVkIGludG8gYSBUT1RQIGFwcCBsaWtlIEdvb2dsZSBBdXRoZW50aWNhdG9yLlxuICAgKiBJZiB0aGUgb3B0aW9uYWwgcGFyYW1ldGVycyBhcmUgdW5zcGVjaWZpZWQsIGFuIGFjY291bnROYW1lIG9mIDx1c2VyRW1haWw+IGFuZCBpc3N1ZXIgb2YgPGZpcmViYXNlQXBwTmFtZT4gYXJlIHVzZWQuXG4gICAqXG4gICAqIEBwYXJhbSBhY2NvdW50TmFtZSB0aGUgbmFtZSBvZiB0aGUgYWNjb3VudC9hcHAgYWxvbmcgd2l0aCBhIHVzZXIgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIGlzc3VlciBpc3N1ZXIgb2YgdGhlIFRPVFAgKGxpa2VseSB0aGUgYXBwIG5hbWUpLlxuICAgKiBAcmV0dXJucyBBIFFSIGNvZGUgVVJMIHN0cmluZy5cbiAgICovXG4gIGdlbmVyYXRlUXJDb2RlVXJsKGFjY291bnROYW1lPzogc3RyaW5nLCBpc3N1ZXI/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGxldCB1c2VEZWZhdWx0cyA9IGZhbHNlO1xuICAgIGlmIChfaXNFbXB0eVN0cmluZyhhY2NvdW50TmFtZSkgfHwgX2lzRW1wdHlTdHJpbmcoaXNzdWVyKSkge1xuICAgICAgdXNlRGVmYXVsdHMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAodXNlRGVmYXVsdHMpIHtcbiAgICAgIGlmIChfaXNFbXB0eVN0cmluZyhhY2NvdW50TmFtZSkpIHtcbiAgICAgICAgYWNjb3VudE5hbWUgPSB0aGlzLmF1dGguY3VycmVudFVzZXI/LmVtYWlsIHx8ICd1bmtub3dudXNlcic7XG4gICAgICB9XG4gICAgICBpZiAoX2lzRW1wdHlTdHJpbmcoaXNzdWVyKSkge1xuICAgICAgICBpc3N1ZXIgPSB0aGlzLmF1dGgubmFtZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGBvdHBhdXRoOi8vdG90cC8ke2lzc3Vlcn06JHthY2NvdW50TmFtZX0/c2VjcmV0PSR7dGhpcy5zZWNyZXRLZXl9Jmlzc3Vlcj0ke2lzc3Vlcn0mYWxnb3JpdGhtPSR7dGhpcy5oYXNoaW5nQWxnb3JpdGhtfSZkaWdpdHM9JHt0aGlzLmNvZGVMZW5ndGh9YDtcbiAgfVxufVxuXG4vKiogQGludGVybmFsICovXG5mdW5jdGlvbiBfaXNFbXB0eVN0cmluZyhpbnB1dD86IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIGlucHV0ID09PSAndW5kZWZpbmVkJyB8fCBpbnB1dD8ubGVuZ3RoID09PSAwO1xufVxuIiwgImV4cG9ydCB7IEEgYXMgQWN0aW9uQ29kZU9wZXJhdGlvbiwgYWogYXMgQWN0aW9uQ29kZVVSTCwgTSBhcyBBdXRoQ3JlZGVudGlhbCwgSiBhcyBBdXRoRXJyb3JDb2RlcywgTiBhcyBFbWFpbEF1dGhDcmVkZW50aWFsLCBXIGFzIEVtYWlsQXV0aFByb3ZpZGVyLCBYIGFzIEZhY2Vib29rQXV0aFByb3ZpZGVyLCBGIGFzIEZhY3RvcklkLCBaIGFzIEdpdGh1YkF1dGhQcm92aWRlciwgWSBhcyBHb29nbGVBdXRoUHJvdmlkZXIsIFEgYXMgT0F1dGhDcmVkZW50aWFsLCBfIGFzIE9BdXRoUHJvdmlkZXIsIE8gYXMgT3BlcmF0aW9uVHlwZSwgVSBhcyBQaG9uZUF1dGhDcmVkZW50aWFsLCBQIGFzIFBob25lQXV0aFByb3ZpZGVyLCBuIGFzIFBob25lTXVsdGlGYWN0b3JHZW5lcmF0b3IsIHEgYXMgUHJvdmlkZXJJZCwgUiBhcyBSZWNhcHRjaGFWZXJpZmllciwgJCBhcyBTQU1MQXV0aFByb3ZpZGVyLCBTIGFzIFNpZ25Jbk1ldGhvZCwgVCBhcyBUb3RwTXVsdGlGYWN0b3JHZW5lcmF0b3IsIG8gYXMgVG90cFNlY3JldCwgYTAgYXMgVHdpdHRlckF1dGhQcm92aWRlciwgYTggYXMgYXBwbHlBY3Rpb25Db2RlLCB5IGFzIGJlZm9yZUF1dGhTdGF0ZUNoYW5nZWQsIGEgYXMgYnJvd3NlckNvb2tpZVBlcnNpc3RlbmNlLCBiIGFzIGJyb3dzZXJMb2NhbFBlcnNpc3RlbmNlLCBtIGFzIGJyb3dzZXJQb3B1cFJlZGlyZWN0UmVzb2x2ZXIsIGMgYXMgYnJvd3NlclNlc3Npb25QZXJzaXN0ZW5jZSwgYTkgYXMgY2hlY2tBY3Rpb25Db2RlLCBhNyBhcyBjb25maXJtUGFzc3dvcmRSZXNldCwgTCBhcyBjb25uZWN0QXV0aEVtdWxhdG9yLCBhYiBhcyBjcmVhdGVVc2VyV2l0aEVtYWlsQW5kUGFzc3dvcmQsIEggYXMgZGVidWdFcnJvck1hcCwgRyBhcyBkZWxldGVVc2VyLCBhZyBhcyBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbCwgYXIgYXMgZ2V0QWRkaXRpb25hbFVzZXJJbmZvLCBwIGFzIGdldEF1dGgsIGFvIGFzIGdldElkVG9rZW4sIGFwIGFzIGdldElkVG9rZW5SZXN1bHQsIGF0IGFzIGdldE11bHRpRmFjdG9yUmVzb2x2ZXIsIGsgYXMgZ2V0UmVkaXJlY3RSZXN1bHQsIFYgYXMgaW5NZW1vcnlQZXJzaXN0ZW5jZSwgaSBhcyBpbmRleGVkREJMb2NhbFBlcnNpc3RlbmNlLCBLIGFzIGluaXRpYWxpemVBdXRoLCB2IGFzIGluaXRpYWxpemVSZWNhcHRjaGFDb25maWcsIGFlIGFzIGlzU2lnbkluV2l0aEVtYWlsTGluaywgYTMgYXMgbGlua1dpdGhDcmVkZW50aWFsLCBsIGFzIGxpbmtXaXRoUGhvbmVOdW1iZXIsIGUgYXMgbGlua1dpdGhQb3B1cCwgaCBhcyBsaW5rV2l0aFJlZGlyZWN0LCBhdSBhcyBtdWx0aUZhY3RvciwgeiBhcyBvbkF1dGhTdGF0ZUNoYW5nZWQsIHggYXMgb25JZFRva2VuQ2hhbmdlZCwgYWsgYXMgcGFyc2VBY3Rpb25Db2RlVVJMLCBJIGFzIHByb2RFcnJvck1hcCwgYTQgYXMgcmVhdXRoZW50aWNhdGVXaXRoQ3JlZGVudGlhbCwgciBhcyByZWF1dGhlbnRpY2F0ZVdpdGhQaG9uZU51bWJlciwgZiBhcyByZWF1dGhlbnRpY2F0ZVdpdGhQb3B1cCwgaiBhcyByZWF1dGhlbnRpY2F0ZVdpdGhSZWRpcmVjdCwgYXMgYXMgcmVsb2FkLCBFIGFzIHJldm9rZUFjY2Vzc1Rva2VuLCBhaCBhcyBzZW5kRW1haWxWZXJpZmljYXRpb24sIGE2IGFzIHNlbmRQYXNzd29yZFJlc2V0RW1haWwsIGFkIGFzIHNlbmRTaWduSW5MaW5rVG9FbWFpbCwgdCBhcyBzZXRQZXJzaXN0ZW5jZSwgYTEgYXMgc2lnbkluQW5vbnltb3VzbHksIGEyIGFzIHNpZ25JbldpdGhDcmVkZW50aWFsLCBhNSBhcyBzaWduSW5XaXRoQ3VzdG9tVG9rZW4sIGFjIGFzIHNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkLCBhZiBhcyBzaWduSW5XaXRoRW1haWxMaW5rLCBzIGFzIHNpZ25JbldpdGhQaG9uZU51bWJlciwgZCBhcyBzaWduSW5XaXRoUG9wdXAsIGcgYXMgc2lnbkluV2l0aFJlZGlyZWN0LCBEIGFzIHNpZ25PdXQsIGFxIGFzIHVubGluaywgQyBhcyB1cGRhdGVDdXJyZW50VXNlciwgYW0gYXMgdXBkYXRlRW1haWwsIGFuIGFzIHVwZGF0ZVBhc3N3b3JkLCB1IGFzIHVwZGF0ZVBob25lTnVtYmVyLCBhbCBhcyB1cGRhdGVQcm9maWxlLCBCIGFzIHVzZURldmljZUxhbmd1YWdlLCB3IGFzIHZhbGlkYXRlUGFzc3dvcmQsIGFpIGFzIHZlcmlmeUJlZm9yZVVwZGF0ZUVtYWlsLCBhYSBhcyB2ZXJpZnlQYXNzd29yZFJlc2V0Q29kZSB9IGZyb20gJy4vdG90cC1jOGQyMDdiOS5qcyc7XG5pbXBvcnQgJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0ICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgJ0BmaXJlYmFzZS9jb21wb25lbnQnO1xuaW1wb3J0ICdAZmlyZWJhc2UvbG9nZ2VyJztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcFxuIiwgImV4cG9ydCAqIGZyb20gJ0BmaXJlYmFzZS9hdXRoJztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4Lm1qcy5tYXBcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuY29uc3QgTE9OR19UWVBFID0gJ3R5cGUuZ29vZ2xlYXBpcy5jb20vZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUnO1xuY29uc3QgVU5TSUdORURfTE9OR19UWVBFID0gJ3R5cGUuZ29vZ2xlYXBpcy5jb20vZ29vZ2xlLnByb3RvYnVmLlVJbnQ2NFZhbHVlJztcblxuZnVuY3Rpb24gbWFwVmFsdWVzKFxuICAvLyB7IFtrOiBzdHJpbmddOiB1bmtub3duIH0gaXMgbm8gbG9uZ2VyIGEgd2lsZGNhcmQgYXNzaWdubWVudCB0YXJnZXQgYWZ0ZXIgdHlwZXNjcmlwdCAzLjVcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgbzogeyBba2V5OiBzdHJpbmddOiBhbnkgfSxcbiAgZjogKGFyZzA6IHVua25vd24pID0+IHVua25vd25cbik6IG9iamVjdCB7XG4gIGNvbnN0IHJlc3VsdDogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0gPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gbykge1xuICAgIGlmIChvLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgIHJlc3VsdFtrZXldID0gZihvW2tleV0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFRha2VzIGRhdGEgYW5kIGVuY29kZXMgaXQgaW4gYSBKU09OLWZyaWVuZGx5IHdheSwgc3VjaCB0aGF0IHR5cGVzIHN1Y2ggYXNcbiAqIERhdGUgYXJlIHByZXNlcnZlZC5cbiAqIEBpbnRlcm5hbFxuICogQHBhcmFtIGRhdGEgLSBEYXRhIHRvIGVuY29kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZShkYXRhOiB1bmtub3duKTogdW5rbm93biB7XG4gIGlmIChkYXRhID09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBpZiAoZGF0YSBpbnN0YW5jZW9mIE51bWJlcikge1xuICAgIGRhdGEgPSBkYXRhLnZhbHVlT2YoKTtcbiAgfVxuICBpZiAodHlwZW9mIGRhdGEgPT09ICdudW1iZXInICYmIGlzRmluaXRlKGRhdGEpKSB7XG4gICAgLy8gQW55IG51bWJlciBpbiBKUyBpcyBzYWZlIHRvIHB1dCBkaXJlY3RseSBpbiBKU09OIGFuZCBwYXJzZSBhcyBhIGRvdWJsZVxuICAgIC8vIHdpdGhvdXQgYW55IGxvc3Mgb2YgcHJlY2lzaW9uLlxuICAgIHJldHVybiBkYXRhO1xuICB9XG4gIGlmIChkYXRhID09PSB0cnVlIHx8IGRhdGEgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cbiAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkYXRhKSA9PT0gJ1tvYmplY3QgU3RyaW5nXScpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuICBpZiAoZGF0YSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICByZXR1cm4gZGF0YS50b0lTT1N0cmluZygpO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgcmV0dXJuIGRhdGEubWFwKHggPT4gZW5jb2RlKHgpKTtcbiAgfVxuICBpZiAodHlwZW9mIGRhdGEgPT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGRhdGEgPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIG1hcFZhbHVlcyhkYXRhISwgeCA9PiBlbmNvZGUoeCkpO1xuICB9XG4gIC8vIElmIHdlIGdvdCB0aGlzIGZhciwgdGhlIGRhdGEgaXMgbm90IGVuY29kYWJsZS5cbiAgdGhyb3cgbmV3IEVycm9yKCdEYXRhIGNhbm5vdCBiZSBlbmNvZGVkIGluIEpTT046ICcgKyBkYXRhKTtcbn1cblxuLyoqXG4gKiBUYWtlcyBkYXRhIHRoYXQncyBiZWVuIGVuY29kZWQgaW4gYSBKU09OLWZyaWVuZGx5IGZvcm0gYW5kIHJldHVybnMgYSBmb3JtXG4gKiB3aXRoIHJpY2hlciBkYXRhdHlwZXMsIHN1Y2ggYXMgRGF0ZXMsIGV0Yy5cbiAqIEBpbnRlcm5hbFxuICogQHBhcmFtIGpzb24gLSBKU09OIHRvIGNvbnZlcnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGUoanNvbjogdW5rbm93bik6IHVua25vd24ge1xuICBpZiAoanNvbiA9PSBudWxsKSB7XG4gICAgcmV0dXJuIGpzb247XG4gIH1cbiAgaWYgKChqc29uIGFzIHsgW2tleTogc3RyaW5nXTogdW5rbm93biB9KVsnQHR5cGUnXSkge1xuICAgIHN3aXRjaCAoKGpzb24gYXMgeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0pWydAdHlwZSddKSB7XG4gICAgICBjYXNlIExPTkdfVFlQRTpcbiAgICAgIC8vIEZhbGwgdGhyb3VnaCBhbmQgaGFuZGxlIHRoaXMgdGhlIHNhbWUgYXMgdW5zaWduZWQuXG4gICAgICBjYXNlIFVOU0lHTkVEX0xPTkdfVFlQRToge1xuICAgICAgICAvLyBUZWNobmljYWxseSwgdGhpcyBjb3VsZCB3b3JrIHJldHVybiBhIHZhbGlkIG51bWJlciBmb3IgbWFsZm9ybWVkXG4gICAgICAgIC8vIGRhdGEgaWYgdGhlcmUgd2FzIGEgbnVtYmVyIGZvbGxvd2VkIGJ5IGdhcmJhZ2UuIEJ1dCBpdCdzIGp1c3Qgbm90XG4gICAgICAgIC8vIHdvcnRoIGFsbCB0aGUgZXh0cmEgY29kZSB0byBkZXRlY3QgdGhhdCBjYXNlLlxuICAgICAgICBjb25zdCB2YWx1ZSA9IE51bWJlcigoanNvbiBhcyB7IFtrZXk6IHN0cmluZ106IHVua25vd24gfSlbJ3ZhbHVlJ10pO1xuICAgICAgICBpZiAoaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEYXRhIGNhbm5vdCBiZSBkZWNvZGVkIGZyb20gSlNPTjogJyArIGpzb24pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEYXRhIGNhbm5vdCBiZSBkZWNvZGVkIGZyb20gSlNPTjogJyArIGpzb24pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAoQXJyYXkuaXNBcnJheShqc29uKSkge1xuICAgIHJldHVybiBqc29uLm1hcCh4ID0+IGRlY29kZSh4KSk7XG4gIH1cbiAgaWYgKHR5cGVvZiBqc29uID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiBqc29uID09PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBtYXBWYWx1ZXMoanNvbiEsIHggPT4gZGVjb2RlKHgpKTtcbiAgfVxuICAvLyBBbnl0aGluZyBlbHNlIGlzIHNhZmUgdG8gcmV0dXJuLlxuICByZXR1cm4ganNvbjtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIFR5cGUgY29uc3RhbnQgZm9yIEZpcmViYXNlIEZ1bmN0aW9ucy5cbiAqL1xuZXhwb3J0IGNvbnN0IEZVTkNUSU9OU19UWVBFID0gJ2Z1bmN0aW9ucyc7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRnVuY3Rpb25zRXJyb3JDb2RlQ29yZSBhcyBGdW5jdGlvbnNFcnJvckNvZGUgfSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBkZWNvZGUgfSBmcm9tICcuL3NlcmlhbGl6ZXInO1xuaW1wb3J0IHsgSHR0cFJlc3BvbnNlQm9keSB9IGZyb20gJy4vc2VydmljZSc7XG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgRlVOQ1RJT05TX1RZUEUgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbi8qKlxuICogU3RhbmRhcmQgZXJyb3IgY29kZXMgZm9yIGRpZmZlcmVudCB3YXlzIGEgcmVxdWVzdCBjYW4gZmFpbCwgYXMgZGVmaW5lZCBieTpcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9nb29nbGVhcGlzL2dvb2dsZWFwaXMvYmxvYi9tYXN0ZXIvZ29vZ2xlL3JwYy9jb2RlLnByb3RvXG4gKlxuICogVGhpcyBtYXAgaXMgdXNlZCBwcmltYXJpbHkgdG8gY29udmVydCBmcm9tIGEgYmFja2VuZCBlcnJvciBjb2RlIHN0cmluZyB0b1xuICogYSBjbGllbnQgU0RLIGVycm9yIGNvZGUgc3RyaW5nLCBhbmQgbWFrZSBzdXJlIGl0J3MgaW4gdGhlIHN1cHBvcnRlZCBzZXQuXG4gKi9cbmNvbnN0IGVycm9yQ29kZU1hcDogeyBbbmFtZTogc3RyaW5nXTogRnVuY3Rpb25zRXJyb3JDb2RlIH0gPSB7XG4gIE9LOiAnb2snLFxuICBDQU5DRUxMRUQ6ICdjYW5jZWxsZWQnLFxuICBVTktOT1dOOiAndW5rbm93bicsXG4gIElOVkFMSURfQVJHVU1FTlQ6ICdpbnZhbGlkLWFyZ3VtZW50JyxcbiAgREVBRExJTkVfRVhDRUVERUQ6ICdkZWFkbGluZS1leGNlZWRlZCcsXG4gIE5PVF9GT1VORDogJ25vdC1mb3VuZCcsXG4gIEFMUkVBRFlfRVhJU1RTOiAnYWxyZWFkeS1leGlzdHMnLFxuICBQRVJNSVNTSU9OX0RFTklFRDogJ3Blcm1pc3Npb24tZGVuaWVkJyxcbiAgVU5BVVRIRU5USUNBVEVEOiAndW5hdXRoZW50aWNhdGVkJyxcbiAgUkVTT1VSQ0VfRVhIQVVTVEVEOiAncmVzb3VyY2UtZXhoYXVzdGVkJyxcbiAgRkFJTEVEX1BSRUNPTkRJVElPTjogJ2ZhaWxlZC1wcmVjb25kaXRpb24nLFxuICBBQk9SVEVEOiAnYWJvcnRlZCcsXG4gIE9VVF9PRl9SQU5HRTogJ291dC1vZi1yYW5nZScsXG4gIFVOSU1QTEVNRU5URUQ6ICd1bmltcGxlbWVudGVkJyxcbiAgSU5URVJOQUw6ICdpbnRlcm5hbCcsXG4gIFVOQVZBSUxBQkxFOiAndW5hdmFpbGFibGUnLFxuICBEQVRBX0xPU1M6ICdkYXRhLWxvc3MnXG59O1xuXG4vKipcbiAqIEFuIGVycm9yIHJldHVybmVkIGJ5IHRoZSBGaXJlYmFzZSBGdW5jdGlvbnMgY2xpZW50IFNESy5cbiAqXG4gKiBTZWUge0BsaW5rIEZ1bmN0aW9uc0Vycm9yQ29kZX0gZm9yIGZ1bGwgZG9jdW1lbnRhdGlvbiBvZiBjb2Rlcy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBGdW5jdGlvbnNFcnJvciBleHRlbmRzIEZpcmViYXNlRXJyb3Ige1xuICAvKipcbiAgICogQ29uc3RydWN0cyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgYEZ1bmN0aW9uc0Vycm9yYCBjbGFzcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIC8qKlxuICAgICAqIEEgc3RhbmRhcmQgZXJyb3IgY29kZSB0aGF0IHdpbGwgYmUgcmV0dXJuZWQgdG8gdGhlIGNsaWVudC4gVGhpcyBhbHNvXG4gICAgICogZGV0ZXJtaW5lcyB0aGUgSFRUUCBzdGF0dXMgY29kZSBvZiB0aGUgcmVzcG9uc2UsIGFzIGRlZmluZWQgaW4gY29kZS5wcm90by5cbiAgICAgKi9cbiAgICBjb2RlOiBGdW5jdGlvbnNFcnJvckNvZGUsXG4gICAgbWVzc2FnZT86IHN0cmluZyxcbiAgICAvKipcbiAgICAgKiBBZGRpdGlvbmFsIGRldGFpbHMgdG8gYmUgY29udmVydGVkIHRvIEpTT04gYW5kIGluY2x1ZGVkIGluIHRoZSBlcnJvciByZXNwb25zZS5cbiAgICAgKi9cbiAgICByZWFkb25seSBkZXRhaWxzPzogdW5rbm93blxuICApIHtcbiAgICBzdXBlcihgJHtGVU5DVElPTlNfVFlQRX0vJHtjb2RlfWAsIG1lc3NhZ2UgfHwgJycpO1xuXG4gICAgLy8gU2luY2UgdGhlIEZpcmViYXNlRXJyb3IgY29uc3RydWN0b3Igc2V0cyB0aGUgcHJvdG90eXBlIG9mIGB0aGlzYCB0byBGaXJlYmFzZUVycm9yLnByb3RvdHlwZSxcbiAgICAvLyB3ZSBhbHNvIGhhdmUgdG8gZG8gaXQgaW4gYWxsIHN1YmNsYXNzZXMgdG8gYWxsb3cgZm9yIGNvcnJlY3QgYGluc3RhbmNlb2ZgIGNoZWNrcy5cbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRnVuY3Rpb25zRXJyb3IucHJvdG90eXBlKTtcbiAgfVxufVxuXG4vKipcbiAqIFRha2VzIGFuIEhUVFAgc3RhdHVzIGNvZGUgYW5kIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgRXJyb3JDb2RlLlxuICogVGhpcyBpcyB0aGUgc3RhbmRhcmQgSFRUUCBzdGF0dXMgY29kZSAtPiBlcnJvciBtYXBwaW5nIGRlZmluZWQgaW46XG4gKiBodHRwczovL2dpdGh1Yi5jb20vZ29vZ2xlYXBpcy9nb29nbGVhcGlzL2Jsb2IvbWFzdGVyL2dvb2dsZS9ycGMvY29kZS5wcm90b1xuICpcbiAqIEBwYXJhbSBzdGF0dXMgQW4gSFRUUCBzdGF0dXMgY29kZS5cbiAqIEByZXR1cm4gVGhlIGNvcnJlc3BvbmRpbmcgRXJyb3JDb2RlLCBvciBFcnJvckNvZGUuVU5LTk9XTiBpZiBub25lLlxuICovXG5mdW5jdGlvbiBjb2RlRm9ySFRUUFN0YXR1cyhzdGF0dXM6IG51bWJlcik6IEZ1bmN0aW9uc0Vycm9yQ29kZSB7XG4gIC8vIE1ha2Ugc3VyZSBhbnkgc3VjY2Vzc2Z1bCBzdGF0dXMgaXMgT0suXG4gIGlmIChzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCkge1xuICAgIHJldHVybiAnb2snO1xuICB9XG4gIHN3aXRjaCAoc3RhdHVzKSB7XG4gICAgY2FzZSAwOlxuICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZSBzZXJ2ZXIgcmV0dXJucyA1MDAuXG4gICAgICByZXR1cm4gJ2ludGVybmFsJztcbiAgICBjYXNlIDQwMDpcbiAgICAgIHJldHVybiAnaW52YWxpZC1hcmd1bWVudCc7XG4gICAgY2FzZSA0MDE6XG4gICAgICByZXR1cm4gJ3VuYXV0aGVudGljYXRlZCc7XG4gICAgY2FzZSA0MDM6XG4gICAgICByZXR1cm4gJ3Blcm1pc3Npb24tZGVuaWVkJztcbiAgICBjYXNlIDQwNDpcbiAgICAgIHJldHVybiAnbm90LWZvdW5kJztcbiAgICBjYXNlIDQwOTpcbiAgICAgIHJldHVybiAnYWJvcnRlZCc7XG4gICAgY2FzZSA0Mjk6XG4gICAgICByZXR1cm4gJ3Jlc291cmNlLWV4aGF1c3RlZCc7XG4gICAgY2FzZSA0OTk6XG4gICAgICByZXR1cm4gJ2NhbmNlbGxlZCc7XG4gICAgY2FzZSA1MDA6XG4gICAgICByZXR1cm4gJ2ludGVybmFsJztcbiAgICBjYXNlIDUwMTpcbiAgICAgIHJldHVybiAndW5pbXBsZW1lbnRlZCc7XG4gICAgY2FzZSA1MDM6XG4gICAgICByZXR1cm4gJ3VuYXZhaWxhYmxlJztcbiAgICBjYXNlIDUwNDpcbiAgICAgIHJldHVybiAnZGVhZGxpbmUtZXhjZWVkZWQnO1xuICAgIGRlZmF1bHQ6IC8vIGlnbm9yZVxuICB9XG4gIHJldHVybiAndW5rbm93bic7XG59XG5cbi8qKlxuICogVGFrZXMgYW4gSFRUUCByZXNwb25zZSBhbmQgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBFcnJvciwgaWYgYW55LlxuICovXG5leHBvcnQgZnVuY3Rpb24gX2Vycm9yRm9yUmVzcG9uc2UoXG4gIHN0YXR1czogbnVtYmVyLFxuICBib2R5SlNPTjogSHR0cFJlc3BvbnNlQm9keSB8IG51bGxcbik6IEVycm9yIHwgbnVsbCB7XG4gIGxldCBjb2RlID0gY29kZUZvckhUVFBTdGF0dXMoc3RhdHVzKTtcblxuICAvLyBTdGFydCB3aXRoIHJlYXNvbmFibGUgZGVmYXVsdHMgZnJvbSB0aGUgc3RhdHVzIGNvZGUuXG4gIGxldCBkZXNjcmlwdGlvbjogc3RyaW5nID0gY29kZTtcblxuICBsZXQgZGV0YWlsczogdW5rbm93biA9IHVuZGVmaW5lZDtcblxuICAvLyBUaGVuIGxvb2sgdGhyb3VnaCB0aGUgYm9keSBmb3IgZXhwbGljaXQgZGV0YWlscy5cbiAgdHJ5IHtcbiAgICBjb25zdCBlcnJvckpTT04gPSBib2R5SlNPTiAmJiBib2R5SlNPTi5lcnJvcjtcbiAgICBpZiAoZXJyb3JKU09OKSB7XG4gICAgICBjb25zdCBzdGF0dXMgPSBlcnJvckpTT04uc3RhdHVzO1xuICAgICAgaWYgKHR5cGVvZiBzdGF0dXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGlmICghZXJyb3JDb2RlTWFwW3N0YXR1c10pIHtcbiAgICAgICAgICAvLyBUaGV5IG11c3QndmUgaW5jbHVkZWQgYW4gdW5rbm93biBlcnJvciBjb2RlIGluIHRoZSBib2R5LlxuICAgICAgICAgIHJldHVybiBuZXcgRnVuY3Rpb25zRXJyb3IoJ2ludGVybmFsJywgJ2ludGVybmFsJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29kZSA9IGVycm9yQ29kZU1hcFtzdGF0dXNdO1xuXG4gICAgICAgIC8vIFRPRE8oa2xpbXQpOiBBZGQgYmV0dGVyIGRlZmF1bHQgZGVzY3JpcHRpb25zIGZvciBlcnJvciBlbnVtcy5cbiAgICAgICAgLy8gVGhlIGRlZmF1bHQgZGVzY3JpcHRpb24gbmVlZHMgdG8gYmUgdXBkYXRlZCBmb3IgdGhlIG5ldyBjb2RlLlxuICAgICAgICBkZXNjcmlwdGlvbiA9IHN0YXR1cztcbiAgICAgIH1cblxuICAgICAgY29uc3QgbWVzc2FnZSA9IGVycm9ySlNPTi5tZXNzYWdlO1xuICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJykge1xuICAgICAgICBkZXNjcmlwdGlvbiA9IG1lc3NhZ2U7XG4gICAgICB9XG5cbiAgICAgIGRldGFpbHMgPSBlcnJvckpTT04uZGV0YWlscztcbiAgICAgIGlmIChkZXRhaWxzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZGV0YWlscyA9IGRlY29kZShkZXRhaWxzKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBJZiB3ZSBjb3VsZG4ndCBwYXJzZSBleHBsaWNpdCBlcnJvciBkYXRhLCB0aGF0J3MgZmluZS5cbiAgfVxuXG4gIGlmIChjb2RlID09PSAnb2snKSB7XG4gICAgLy8gVGVjaG5pY2FsbHksIHRoZXJlJ3MgYW4gZWRnZSBjYXNlIHdoZXJlIGEgZGV2ZWxvcGVyIGNvdWxkIGV4cGxpY2l0bHlcbiAgICAvLyByZXR1cm4gYW4gZXJyb3IgY29kZSBvZiBPSywgYW5kIHdlIHdpbGwgdHJlYXQgaXQgYXMgc3VjY2VzcywgYnV0IHRoYXRcbiAgICAvLyBzZWVtcyByZWFzb25hYmxlLlxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBGdW5jdGlvbnNFcnJvcihjb2RlLCBkZXNjcmlwdGlvbiwgZGV0YWlscyk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwLCBGaXJlYmFzZUFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHtcbiAgQXBwQ2hlY2tJbnRlcm5hbENvbXBvbmVudE5hbWUsXG4gIEZpcmViYXNlQXBwQ2hlY2tJbnRlcm5hbFxufSBmcm9tICdAZmlyZWJhc2UvYXBwLWNoZWNrLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHtcbiAgTWVzc2FnaW5nSW50ZXJuYWwsXG4gIE1lc3NhZ2luZ0ludGVybmFsQ29tcG9uZW50TmFtZVxufSBmcm9tICdAZmlyZWJhc2UvbWVzc2FnaW5nLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHtcbiAgRmlyZWJhc2VBdXRoSW50ZXJuYWwsXG4gIEZpcmViYXNlQXV0aEludGVybmFsTmFtZVxufSBmcm9tICdAZmlyZWJhc2UvYXV0aC1pbnRlcm9wLXR5cGVzJztcblxuLyoqXG4gKiBUaGUgbWV0YWRhdGEgdGhhdCBzaG91bGQgYmUgc3VwcGxpZWQgd2l0aCBmdW5jdGlvbiBjYWxscy5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRleHQge1xuICBhdXRoVG9rZW4/OiBzdHJpbmc7XG4gIG1lc3NhZ2luZ1Rva2VuPzogc3RyaW5nO1xuICBhcHBDaGVja1Rva2VuOiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKipcbiAqIEhlbHBlciBjbGFzcyB0byBnZXQgbWV0YWRhdGEgdGhhdCBzaG91bGQgYmUgaW5jbHVkZWQgd2l0aCBhIGZ1bmN0aW9uIGNhbGwuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIENvbnRleHRQcm92aWRlciB7XG4gIHByaXZhdGUgYXV0aDogRmlyZWJhc2VBdXRoSW50ZXJuYWwgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBtZXNzYWdpbmc6IE1lc3NhZ2luZ0ludGVybmFsIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgYXBwQ2hlY2s6IEZpcmViYXNlQXBwQ2hlY2tJbnRlcm5hbCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNlcnZlckFwcEFwcENoZWNrVG9rZW46IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBhcHA6IEZpcmViYXNlQXBwLFxuICAgIGF1dGhQcm92aWRlcjogUHJvdmlkZXI8RmlyZWJhc2VBdXRoSW50ZXJuYWxOYW1lPixcbiAgICBtZXNzYWdpbmdQcm92aWRlcjogUHJvdmlkZXI8TWVzc2FnaW5nSW50ZXJuYWxDb21wb25lbnROYW1lPixcbiAgICBhcHBDaGVja1Byb3ZpZGVyOiBQcm92aWRlcjxBcHBDaGVja0ludGVybmFsQ29tcG9uZW50TmFtZT5cbiAgKSB7XG4gICAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGFwcCkgJiYgYXBwLnNldHRpbmdzLmFwcENoZWNrVG9rZW4pIHtcbiAgICAgIHRoaXMuc2VydmVyQXBwQXBwQ2hlY2tUb2tlbiA9IGFwcC5zZXR0aW5ncy5hcHBDaGVja1Rva2VuO1xuICAgIH1cbiAgICB0aGlzLmF1dGggPSBhdXRoUHJvdmlkZXIuZ2V0SW1tZWRpYXRlKHsgb3B0aW9uYWw6IHRydWUgfSk7XG4gICAgdGhpcy5tZXNzYWdpbmcgPSBtZXNzYWdpbmdQcm92aWRlci5nZXRJbW1lZGlhdGUoe1xuICAgICAgb3B0aW9uYWw6IHRydWVcbiAgICB9KTtcblxuICAgIGlmICghdGhpcy5hdXRoKSB7XG4gICAgICBhdXRoUHJvdmlkZXIuZ2V0KCkudGhlbihcbiAgICAgICAgYXV0aCA9PiAodGhpcy5hdXRoID0gYXV0aCksXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICAvKiBnZXQoKSBuZXZlciByZWplY3RzICovXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLm1lc3NhZ2luZykge1xuICAgICAgbWVzc2FnaW5nUHJvdmlkZXIuZ2V0KCkudGhlbihcbiAgICAgICAgbWVzc2FnaW5nID0+ICh0aGlzLm1lc3NhZ2luZyA9IG1lc3NhZ2luZyksXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICAvKiBnZXQoKSBuZXZlciByZWplY3RzICovXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmFwcENoZWNrKSB7XG4gICAgICBhcHBDaGVja1Byb3ZpZGVyPy5nZXQoKS50aGVuKFxuICAgICAgICBhcHBDaGVjayA9PiAodGhpcy5hcHBDaGVjayA9IGFwcENoZWNrKSxcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIC8qIGdldCgpIG5ldmVyIHJlamVjdHMgKi9cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBnZXRBdXRoVG9rZW4oKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAoIXRoaXMuYXV0aCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCB0aGlzLmF1dGguZ2V0VG9rZW4oKTtcbiAgICAgIHJldHVybiB0b2tlbj8uYWNjZXNzVG9rZW47XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gSWYgdGhlcmUncyBhbnkgZXJyb3Igd2hlbiB0cnlpbmcgdG8gZ2V0IHRoZSBhdXRoIHRva2VuLCBsZWF2ZSBpdCBvZmYuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldE1lc3NhZ2luZ1Rva2VuKCk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMubWVzc2FnaW5nIHx8XG4gICAgICAhKCdOb3RpZmljYXRpb24nIGluIHNlbGYpIHx8XG4gICAgICBOb3RpZmljYXRpb24ucGVybWlzc2lvbiAhPT0gJ2dyYW50ZWQnXG4gICAgKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5tZXNzYWdpbmcuZ2V0VG9rZW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBXZSBkb24ndCB3YXJuIG9uIHRoaXMsIGJlY2F1c2UgaXQgdXN1YWxseSBtZWFucyBtZXNzYWdpbmcgaXNuJ3Qgc2V0IHVwLlxuICAgICAgLy8gY29uc29sZS53YXJuKCdGYWlsZWQgdG8gcmV0cmlldmUgaW5zdGFuY2UgaWQgdG9rZW4uJywgZSk7XG5cbiAgICAgIC8vIElmIHRoZXJlJ3MgYW55IGVycm9yIHdoZW4gdHJ5aW5nIHRvIGdldCB0aGUgdG9rZW4sIGxlYXZlIGl0IG9mZi5cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0QXBwQ2hlY2tUb2tlbihcbiAgICBsaW1pdGVkVXNlQXBwQ2hlY2tUb2tlbnM/OiBib29sZWFuXG4gICk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGlmICh0aGlzLnNlcnZlckFwcEFwcENoZWNrVG9rZW4pIHtcbiAgICAgIHJldHVybiB0aGlzLnNlcnZlckFwcEFwcENoZWNrVG9rZW47XG4gICAgfVxuICAgIGlmICh0aGlzLmFwcENoZWNrKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBsaW1pdGVkVXNlQXBwQ2hlY2tUb2tlbnNcbiAgICAgICAgPyBhd2FpdCB0aGlzLmFwcENoZWNrLmdldExpbWl0ZWRVc2VUb2tlbigpXG4gICAgICAgIDogYXdhaXQgdGhpcy5hcHBDaGVjay5nZXRUb2tlbigpO1xuICAgICAgaWYgKHJlc3VsdC5lcnJvcikge1xuICAgICAgICAvLyBEbyBub3Qgc2VuZCB0aGUgQXBwIENoZWNrIGhlYWRlciB0byB0aGUgZnVuY3Rpb25zIGVuZHBvaW50IGlmXG4gICAgICAgIC8vIHRoZXJlIHdhcyBhbiBlcnJvciBmcm9tIHRoZSBBcHAgQ2hlY2sgZXhjaGFuZ2UgZW5kcG9pbnQuIFRoZSBBcHBcbiAgICAgICAgLy8gQ2hlY2sgU0RLIHdpbGwgYWxyZWFkeSBoYXZlIGxvZ2dlZCB0aGUgZXJyb3IgdG8gY29uc29sZS5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0LnRva2VuO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGdldENvbnRleHQobGltaXRlZFVzZUFwcENoZWNrVG9rZW5zPzogYm9vbGVhbik6IFByb21pc2U8Q29udGV4dD4ge1xuICAgIGNvbnN0IGF1dGhUb2tlbiA9IGF3YWl0IHRoaXMuZ2V0QXV0aFRva2VuKCk7XG4gICAgY29uc3QgbWVzc2FnaW5nVG9rZW4gPSBhd2FpdCB0aGlzLmdldE1lc3NhZ2luZ1Rva2VuKCk7XG4gICAgY29uc3QgYXBwQ2hlY2tUb2tlbiA9IGF3YWl0IHRoaXMuZ2V0QXBwQ2hlY2tUb2tlbihsaW1pdGVkVXNlQXBwQ2hlY2tUb2tlbnMpO1xuICAgIHJldHVybiB7IGF1dGhUb2tlbiwgbWVzc2FnaW5nVG9rZW4sIGFwcENoZWNrVG9rZW4gfTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEZpcmViYXNlQXBwLCBfRmlyZWJhc2VTZXJ2aWNlIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQge1xuICBIdHRwc0NhbGxhYmxlLFxuICBIdHRwc0NhbGxhYmxlUmVzdWx0LFxuICBIdHRwc0NhbGxhYmxlU3RyZWFtUmVzdWx0LFxuICBIdHRwc0NhbGxhYmxlT3B0aW9ucyxcbiAgSHR0cHNDYWxsYWJsZVN0cmVhbU9wdGlvbnNcbn0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHsgX2Vycm9yRm9yUmVzcG9uc2UsIEZ1bmN0aW9uc0Vycm9yIH0gZnJvbSAnLi9lcnJvcic7XG5pbXBvcnQgeyBDb250ZXh0UHJvdmlkZXIgfSBmcm9tICcuL2NvbnRleHQnO1xuaW1wb3J0IHsgZW5jb2RlLCBkZWNvZGUgfSBmcm9tICcuL3NlcmlhbGl6ZXInO1xuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IEZpcmViYXNlQXV0aEludGVybmFsTmFtZSB9IGZyb20gJ0BmaXJlYmFzZS9hdXRoLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHsgTWVzc2FnaW5nSW50ZXJuYWxDb21wb25lbnROYW1lIH0gZnJvbSAnQGZpcmViYXNlL21lc3NhZ2luZy1pbnRlcm9wLXR5cGVzJztcbmltcG9ydCB7IEFwcENoZWNrSW50ZXJuYWxDb21wb25lbnROYW1lIH0gZnJvbSAnQGZpcmViYXNlL2FwcC1jaGVjay1pbnRlcm9wLXR5cGVzJztcbmltcG9ydCB7XG4gIGlzQ2xvdWRXb3Jrc3RhdGlvbixcbiAgcGluZ1NlcnZlcixcbiAgdXBkYXRlRW11bGF0b3JCYW5uZXJcbn0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9SRUdJT04gPSAndXMtY2VudHJhbDEnO1xuXG5jb25zdCByZXNwb25zZUxpbmVSRSA9IC9eZGF0YTogKC4qPykoPzpcXG58JCkvO1xuXG4vKipcbiAqIFRoZSByZXNwb25zZSB0byBhbiBodHRwIHJlcXVlc3QuXG4gKi9cbmludGVyZmFjZSBIdHRwUmVzcG9uc2Uge1xuICBzdGF0dXM6IG51bWJlcjtcbiAganNvbjogSHR0cFJlc3BvbnNlQm9keSB8IG51bGw7XG59XG4vKipcbiAqIERlc2NyaWJlcyB0aGUgc2hhcGUgb2YgdGhlIEh0dHBSZXNwb25zZSBib2R5LlxuICogSXQgbWFrZXMgZnVuY3Rpb25zIHRoYXQgd291bGQgb3RoZXJ3aXNlIHRha2Uge30gYWJsZSB0byBhY2Nlc3MgdGhlXG4gKiBwb3NzaWJsZSBlbGVtZW50cyBpbiB0aGUgYm9keSBtb3JlIGVhc2lseVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEh0dHBSZXNwb25zZUJvZHkge1xuICBkYXRhPzogdW5rbm93bjtcbiAgcmVzdWx0PzogdW5rbm93bjtcbiAgZXJyb3I/OiB7XG4gICAgbWVzc2FnZT86IHVua25vd247XG4gICAgc3RhdHVzPzogdW5rbm93bjtcbiAgICBkZXRhaWxzPzogdW5rbm93bjtcbiAgfTtcbn1cblxuaW50ZXJmYWNlIENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gIHByb21pc2U6IFByb21pc2U8VD47XG4gIGNhbmNlbDogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgUHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVqZWN0ZWQgYWZ0ZXIgdGhlIGdpdmVuIGR1cmF0aW9uLlxuICogVGhlIGVycm9yIHdpbGwgYmUgb2YgdHlwZSBGdW5jdGlvbnNFcnJvci5cbiAqXG4gKiBAcGFyYW0gbWlsbGlzIE51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gd2FpdCBiZWZvcmUgcmVqZWN0aW5nLlxuICovXG5mdW5jdGlvbiBmYWlsQWZ0ZXIobWlsbGlzOiBudW1iZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8bmV2ZXI+IHtcbiAgLy8gTm9kZSB0aW1lcnMgYW5kIGJyb3dzZXIgdGltZXJzIGFyZSBmdW5kYW1lbnRhbGx5IGluY29tcGF0aWJsZSwgYnV0IHdlXG4gIC8vIGRvbid0IGNhcmUgYWJvdXQgdGhlIHZhbHVlIGhlcmVcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgbGV0IHRpbWVyOiBhbnkgfCBudWxsID0gbnVsbDtcbiAgcmV0dXJuIHtcbiAgICBwcm9taXNlOiBuZXcgUHJvbWlzZSgoXywgcmVqZWN0KSA9PiB7XG4gICAgICB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICByZWplY3QobmV3IEZ1bmN0aW9uc0Vycm9yKCdkZWFkbGluZS1leGNlZWRlZCcsICdkZWFkbGluZS1leGNlZWRlZCcpKTtcbiAgICAgIH0sIG1pbGxpcyk7XG4gICAgfSksXG4gICAgY2FuY2VsOiAoKSA9PiB7XG4gICAgICBpZiAodGltZXIpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogVGhlIG1haW4gY2xhc3MgZm9yIHRoZSBGaXJlYmFzZSBGdW5jdGlvbnMgU0RLLlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBGdW5jdGlvbnNTZXJ2aWNlIGltcGxlbWVudHMgX0ZpcmViYXNlU2VydmljZSB7XG4gIHJlYWRvbmx5IGNvbnRleHRQcm92aWRlcjogQ29udGV4dFByb3ZpZGVyO1xuICBlbXVsYXRvck9yaWdpbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGNhbmNlbEFsbFJlcXVlc3RzOiBQcm9taXNlPHZvaWQ+O1xuICBkZWxldGVTZXJ2aWNlITogKCkgPT4gUHJvbWlzZTx2b2lkPjtcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIGN1c3RvbURvbWFpbjogc3RyaW5nIHwgbnVsbDtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBGdW5jdGlvbnMgc2VydmljZSBmb3IgdGhlIGdpdmVuIGFwcC5cbiAgICogQHBhcmFtIGFwcCAtIFRoZSBGaXJlYmFzZUFwcCB0byB1c2UuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBhcHA6IEZpcmViYXNlQXBwLFxuICAgIGF1dGhQcm92aWRlcjogUHJvdmlkZXI8RmlyZWJhc2VBdXRoSW50ZXJuYWxOYW1lPixcbiAgICBtZXNzYWdpbmdQcm92aWRlcjogUHJvdmlkZXI8TWVzc2FnaW5nSW50ZXJuYWxDb21wb25lbnROYW1lPixcbiAgICBhcHBDaGVja1Byb3ZpZGVyOiBQcm92aWRlcjxBcHBDaGVja0ludGVybmFsQ29tcG9uZW50TmFtZT4sXG4gICAgcmVnaW9uT3JDdXN0b21Eb21haW46IHN0cmluZyA9IERFRkFVTFRfUkVHSU9OLFxuICAgIHJlYWRvbmx5IGZldGNoSW1wbDogdHlwZW9mIGZldGNoID0gKC4uLmFyZ3MpID0+IGZldGNoKC4uLmFyZ3MpXG4gICkge1xuICAgIHRoaXMuY29udGV4dFByb3ZpZGVyID0gbmV3IENvbnRleHRQcm92aWRlcihcbiAgICAgIGFwcCxcbiAgICAgIGF1dGhQcm92aWRlcixcbiAgICAgIG1lc3NhZ2luZ1Byb3ZpZGVyLFxuICAgICAgYXBwQ2hlY2tQcm92aWRlclxuICAgICk7XG4gICAgLy8gQ2FuY2VscyBhbGwgb25nb2luZyByZXF1ZXN0cyB3aGVuIHJlc29sdmVkLlxuICAgIHRoaXMuY2FuY2VsQWxsUmVxdWVzdHMgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuZGVsZXRlU2VydmljZSA9ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXNvbHZlKCkpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIFJlc29sdmUgdGhlIHJlZ2lvbiBvciBjdXN0b20gZG9tYWluIG92ZXJsb2FkIGJ5IGF0dGVtcHRpbmcgdG8gcGFyc2UgaXQuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVnaW9uT3JDdXN0b21Eb21haW4pO1xuICAgICAgdGhpcy5jdXN0b21Eb21haW4gPVxuICAgICAgICB1cmwub3JpZ2luICsgKHVybC5wYXRobmFtZSA9PT0gJy8nID8gJycgOiB1cmwucGF0aG5hbWUpO1xuICAgICAgdGhpcy5yZWdpb24gPSBERUZBVUxUX1JFR0lPTjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmN1c3RvbURvbWFpbiA9IG51bGw7XG4gICAgICB0aGlzLnJlZ2lvbiA9IHJlZ2lvbk9yQ3VzdG9tRG9tYWluO1xuICAgIH1cbiAgfVxuXG4gIF9kZWxldGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZXRlU2VydmljZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFVSTCBmb3IgYSBjYWxsYWJsZSB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjYWxsYWJsZS5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBfdXJsKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgcHJvamVjdElkID0gdGhpcy5hcHAub3B0aW9ucy5wcm9qZWN0SWQ7XG4gICAgaWYgKHRoaXMuZW11bGF0b3JPcmlnaW4gIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IG9yaWdpbiA9IHRoaXMuZW11bGF0b3JPcmlnaW47XG4gICAgICByZXR1cm4gYCR7b3JpZ2lufS8ke3Byb2plY3RJZH0vJHt0aGlzLnJlZ2lvbn0vJHtuYW1lfWA7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY3VzdG9tRG9tYWluICE9PSBudWxsKSB7XG4gICAgICByZXR1cm4gYCR7dGhpcy5jdXN0b21Eb21haW59LyR7bmFtZX1gO1xuICAgIH1cblxuICAgIHJldHVybiBgaHR0cHM6Ly8ke3RoaXMucmVnaW9ufS0ke3Byb2plY3RJZH0uY2xvdWRmdW5jdGlvbnMubmV0LyR7bmFtZX1gO1xuICB9XG59XG5cbi8qKlxuICogTW9kaWZ5IHRoaXMgaW5zdGFuY2UgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgQ2xvdWQgRnVuY3Rpb25zIGVtdWxhdG9yLlxuICpcbiAqIE5vdGU6IHRoaXMgbXVzdCBiZSBjYWxsZWQgYmVmb3JlIHRoaXMgaW5zdGFuY2UgaGFzIGJlZW4gdXNlZCB0byBkbyBhbnkgb3BlcmF0aW9ucy5cbiAqXG4gKiBAcGFyYW0gaG9zdCBUaGUgZW11bGF0b3IgaG9zdCAoZXg6IGxvY2FsaG9zdClcbiAqIEBwYXJhbSBwb3J0IFRoZSBlbXVsYXRvciBwb3J0IChleDogNTAwMSlcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3RGdW5jdGlvbnNFbXVsYXRvcihcbiAgZnVuY3Rpb25zSW5zdGFuY2U6IEZ1bmN0aW9uc1NlcnZpY2UsXG4gIGhvc3Q6IHN0cmluZyxcbiAgcG9ydDogbnVtYmVyXG4pOiB2b2lkIHtcbiAgY29uc3QgdXNlU3NsID0gaXNDbG91ZFdvcmtzdGF0aW9uKGhvc3QpO1xuICBmdW5jdGlvbnNJbnN0YW5jZS5lbXVsYXRvck9yaWdpbiA9IGBodHRwJHtcbiAgICB1c2VTc2wgPyAncycgOiAnJ1xuICB9Oi8vJHtob3N0fToke3BvcnR9YDtcbiAgLy8gV29ya2Fyb3VuZCB0byBnZXQgY29va2llcyBpbiBGaXJlYmFzZSBTdHVkaW9cbiAgaWYgKHVzZVNzbCkge1xuICAgIHZvaWQgcGluZ1NlcnZlcihmdW5jdGlvbnNJbnN0YW5jZS5lbXVsYXRvck9yaWdpbiArICcvYmFja2VuZHMnKTtcbiAgICB1cGRhdGVFbXVsYXRvckJhbm5lcignRnVuY3Rpb25zJywgdHJ1ZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBjYWxsYWJsZSBodHRwcyB0cmlnZ2VyIHdpdGggdGhlIGdpdmVuIG5hbWUuXG4gKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0cmlnZ2VyLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhID0gdW5rbm93bj4oXG4gIGZ1bmN0aW9uc0luc3RhbmNlOiBGdW5jdGlvbnNTZXJ2aWNlLFxuICBuYW1lOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBIdHRwc0NhbGxhYmxlT3B0aW9uc1xuKTogSHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPiB7XG4gIGNvbnN0IGNhbGxhYmxlID0gKFxuICAgIGRhdGE/OiBSZXF1ZXN0RGF0YSB8IG51bGxcbiAgKTogUHJvbWlzZTxIdHRwc0NhbGxhYmxlUmVzdWx0PiA9PiB7XG4gICAgcmV0dXJuIGNhbGwoZnVuY3Rpb25zSW5zdGFuY2UsIG5hbWUsIGRhdGEsIG9wdGlvbnMgfHwge30pO1xuICB9O1xuXG4gIGNhbGxhYmxlLnN0cmVhbSA9IChcbiAgICBkYXRhPzogUmVxdWVzdERhdGEgfCBudWxsLFxuICAgIG9wdGlvbnM/OiBIdHRwc0NhbGxhYmxlU3RyZWFtT3B0aW9uc1xuICApID0+IHtcbiAgICByZXR1cm4gc3RyZWFtKGZ1bmN0aW9uc0luc3RhbmNlLCBuYW1lLCBkYXRhLCBvcHRpb25zKTtcbiAgfTtcblxuICByZXR1cm4gY2FsbGFibGUgYXMgSHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPjtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBjYWxsYWJsZSBodHRwcyB0cmlnZ2VyIHdpdGggdGhlIGdpdmVuIHVybC5cbiAqIEBwYXJhbSB1cmwgLSBUaGUgdXJsIG9mIHRoZSB0cmlnZ2VyLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaHR0cHNDYWxsYWJsZUZyb21VUkw8XG4gIFJlcXVlc3REYXRhLFxuICBSZXNwb25zZURhdGEsXG4gIFN0cmVhbURhdGEgPSB1bmtub3duXG4+KFxuICBmdW5jdGlvbnNJbnN0YW5jZTogRnVuY3Rpb25zU2VydmljZSxcbiAgdXJsOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBIdHRwc0NhbGxhYmxlT3B0aW9uc1xuKTogSHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPiB7XG4gIGNvbnN0IGNhbGxhYmxlID0gKFxuICAgIGRhdGE/OiBSZXF1ZXN0RGF0YSB8IG51bGxcbiAgKTogUHJvbWlzZTxIdHRwc0NhbGxhYmxlUmVzdWx0PiA9PiB7XG4gICAgcmV0dXJuIGNhbGxBdFVSTChmdW5jdGlvbnNJbnN0YW5jZSwgdXJsLCBkYXRhLCBvcHRpb25zIHx8IHt9KTtcbiAgfTtcblxuICBjYWxsYWJsZS5zdHJlYW0gPSAoXG4gICAgZGF0YT86IFJlcXVlc3REYXRhIHwgbnVsbCxcbiAgICBvcHRpb25zPzogSHR0cHNDYWxsYWJsZVN0cmVhbU9wdGlvbnNcbiAgKSA9PiB7XG4gICAgcmV0dXJuIHN0cmVhbUF0VVJMKGZ1bmN0aW9uc0luc3RhbmNlLCB1cmwsIGRhdGEsIG9wdGlvbnMgfHwge30pO1xuICB9O1xuICByZXR1cm4gY2FsbGFibGUgYXMgSHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPjtcbn1cblxuZnVuY3Rpb24gZ2V0Q3JlZGVudGlhbHMoXG4gIGZ1bmN0aW9uc0luc3RhbmNlOiBGdW5jdGlvbnNTZXJ2aWNlXG4pOiAnaW5jbHVkZScgfCB1bmRlZmluZWQge1xuICByZXR1cm4gZnVuY3Rpb25zSW5zdGFuY2UuZW11bGF0b3JPcmlnaW4gJiZcbiAgICBpc0Nsb3VkV29ya3N0YXRpb24oZnVuY3Rpb25zSW5zdGFuY2UuZW11bGF0b3JPcmlnaW4pXG4gICAgPyAnaW5jbHVkZSdcbiAgICA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBEb2VzIGFuIEhUVFAgUE9TVCBhbmQgcmV0dXJucyB0aGUgY29tcGxldGVkIHJlc3BvbnNlLlxuICogQHBhcmFtIHVybCBUaGUgdXJsIHRvIHBvc3QgdG8uXG4gKiBAcGFyYW0gYm9keSBUaGUgSlNPTiBib2R5IG9mIHRoZSBwb3N0LlxuICogQHBhcmFtIGhlYWRlcnMgVGhlIEhUVFAgaGVhZGVycyB0byBpbmNsdWRlIGluIHRoZSByZXF1ZXN0LlxuICogQHBhcmFtIGZ1bmN0aW9uc0luc3RhbmNlIGZ1bmN0aW9ucyBpbnN0YW5jZSB0aGF0IGlzIGNhbGxpbmcgcG9zdEpTT05cbiAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgd2lsbCBzdWNjZWVkIHdoZW4gdGhlIHJlcXVlc3QgZmluaXNoZXMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHBvc3RKU09OKFxuICB1cmw6IHN0cmluZyxcbiAgYm9keTogdW5rbm93bixcbiAgaGVhZGVyczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgZmV0Y2hJbXBsOiB0eXBlb2YgZmV0Y2gsXG4gIGZ1bmN0aW9uc0luc3RhbmNlOiBGdW5jdGlvbnNTZXJ2aWNlXG4pOiBQcm9taXNlPEh0dHBSZXNwb25zZT4ge1xuICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9ICdhcHBsaWNhdGlvbi9qc29uJztcblxuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlO1xuICB0cnkge1xuICAgIHJlc3BvbnNlID0gYXdhaXQgZmV0Y2hJbXBsKHVybCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBjcmVkZW50aWFsczogZ2V0Q3JlZGVudGlhbHMoZnVuY3Rpb25zSW5zdGFuY2UpXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBUaGlzIGNvdWxkIGJlIGFuIHVuaGFuZGxlZCBlcnJvciBvbiB0aGUgYmFja2VuZCwgb3IgaXQgY291bGQgYmUgYVxuICAgIC8vIG5ldHdvcmsgZXJyb3IuIFRoZXJlJ3Mgbm8gd2F5IHRvIGtub3csIHNpbmNlIGFuIHVuaGFuZGxlZCBlcnJvciBvbiB0aGVcbiAgICAvLyBiYWNrZW5kIHdpbGwgZmFpbCB0byBzZXQgdGhlIHByb3BlciBDT1JTIGhlYWRlciwgYW5kIHRodXMgd2lsbCBiZVxuICAgIC8vIHRyZWF0ZWQgYXMgYSBuZXR3b3JrIGVycm9yIGJ5IGZldGNoLlxuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6IDAsXG4gICAgICBqc29uOiBudWxsXG4gICAgfTtcbiAgfVxuICBsZXQganNvbjogSHR0cFJlc3BvbnNlQm9keSB8IG51bGwgPSBudWxsO1xuICB0cnkge1xuICAgIGpzb24gPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBJZiB3ZSBmYWlsIHRvIHBhcnNlIEpTT04sIGl0IHdpbGwgZmFpbCB0aGUgc2FtZSBhcyBhbiBlbXB0eSBib2R5LlxuICB9XG4gIHJldHVybiB7XG4gICAgc3RhdHVzOiByZXNwb25zZS5zdGF0dXMsXG4gICAganNvblxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYXV0aG9yaXphdGlvbiBoZWFkZXJzIGZvciBGaXJlYmFzZSBGdW5jdGlvbnMgcmVxdWVzdHMuXG4gKiBAcGFyYW0gZnVuY3Rpb25zSW5zdGFuY2UgVGhlIEZpcmViYXNlIEZ1bmN0aW9ucyBzZXJ2aWNlIGluc3RhbmNlLlxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBmb3IgdGhlIGNhbGxhYmxlIGZ1bmN0aW9uLCBpbmNsdWRpbmcgQXBwQ2hlY2sgdG9rZW4gc2V0dGluZ3MuXG4gKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIGEgaGVhZGVycyBtYXAgdG8gaW5jbHVkZSBpbiBvdXRnb2luZyBmZXRjaCByZXF1ZXN0LlxuICovXG5hc3luYyBmdW5jdGlvbiBtYWtlQXV0aEhlYWRlcnMoXG4gIGZ1bmN0aW9uc0luc3RhbmNlOiBGdW5jdGlvbnNTZXJ2aWNlLFxuICBvcHRpb25zOiBIdHRwc0NhbGxhYmxlT3B0aW9uc1xuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiB7XG4gIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgY29uc3QgY29udGV4dCA9IGF3YWl0IGZ1bmN0aW9uc0luc3RhbmNlLmNvbnRleHRQcm92aWRlci5nZXRDb250ZXh0KFxuICAgIG9wdGlvbnMubGltaXRlZFVzZUFwcENoZWNrVG9rZW5zXG4gICk7XG4gIGlmIChjb250ZXh0LmF1dGhUb2tlbikge1xuICAgIGhlYWRlcnNbJ0F1dGhvcml6YXRpb24nXSA9ICdCZWFyZXIgJyArIGNvbnRleHQuYXV0aFRva2VuO1xuICB9XG4gIGlmIChjb250ZXh0Lm1lc3NhZ2luZ1Rva2VuKSB7XG4gICAgaGVhZGVyc1snRmlyZWJhc2UtSW5zdGFuY2UtSUQtVG9rZW4nXSA9IGNvbnRleHQubWVzc2FnaW5nVG9rZW47XG4gIH1cbiAgaWYgKGNvbnRleHQuYXBwQ2hlY2tUb2tlbiAhPT0gbnVsbCkge1xuICAgIGhlYWRlcnNbJ1gtRmlyZWJhc2UtQXBwQ2hlY2snXSA9IGNvbnRleHQuYXBwQ2hlY2tUb2tlbjtcbiAgfVxuICByZXR1cm4gaGVhZGVycztcbn1cblxuLyoqXG4gKiBDYWxscyBhIGNhbGxhYmxlIGZ1bmN0aW9uIGFzeW5jaHJvbm91c2x5IGFuZCByZXR1cm5zIHRoZSByZXN1bHQuXG4gKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgY2FsbGFibGUgdHJpZ2dlci5cbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIHBhc3MgYXMgcGFyYW1zIHRvIHRoZSBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY2FsbChcbiAgZnVuY3Rpb25zSW5zdGFuY2U6IEZ1bmN0aW9uc1NlcnZpY2UsXG4gIG5hbWU6IHN0cmluZyxcbiAgZGF0YTogdW5rbm93bixcbiAgb3B0aW9uczogSHR0cHNDYWxsYWJsZU9wdGlvbnNcbik6IFByb21pc2U8SHR0cHNDYWxsYWJsZVJlc3VsdD4ge1xuICBjb25zdCB1cmwgPSBmdW5jdGlvbnNJbnN0YW5jZS5fdXJsKG5hbWUpO1xuICByZXR1cm4gY2FsbEF0VVJMKGZ1bmN0aW9uc0luc3RhbmNlLCB1cmwsIGRhdGEsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIENhbGxzIGEgY2FsbGFibGUgZnVuY3Rpb24gYXN5bmNocm9ub3VzbHkgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqIEBwYXJhbSB1cmwgVGhlIHVybCBvZiB0aGUgY2FsbGFibGUgdHJpZ2dlci5cbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIHBhc3MgYXMgcGFyYW1zIHRvIHRoZSBmdW5jdGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY2FsbEF0VVJMKFxuICBmdW5jdGlvbnNJbnN0YW5jZTogRnVuY3Rpb25zU2VydmljZSxcbiAgdXJsOiBzdHJpbmcsXG4gIGRhdGE6IHVua25vd24sXG4gIG9wdGlvbnM6IEh0dHBzQ2FsbGFibGVPcHRpb25zXG4pOiBQcm9taXNlPEh0dHBzQ2FsbGFibGVSZXN1bHQ+IHtcbiAgLy8gRW5jb2RlIGFueSBzcGVjaWFsIHR5cGVzLCBzdWNoIGFzIGRhdGVzLCBpbiB0aGUgaW5wdXQgZGF0YS5cbiAgZGF0YSA9IGVuY29kZShkYXRhKTtcbiAgY29uc3QgYm9keSA9IHsgZGF0YSB9O1xuXG4gIC8vIEFkZCBhIGhlYWRlciBmb3IgdGhlIGF1dGhUb2tlbi5cbiAgY29uc3QgaGVhZGVycyA9IGF3YWl0IG1ha2VBdXRoSGVhZGVycyhmdW5jdGlvbnNJbnN0YW5jZSwgb3B0aW9ucyk7XG5cbiAgLy8gRGVmYXVsdCB0aW1lb3V0IHRvIDcwcywgYnV0IGxldCB0aGUgb3B0aW9ucyBvdmVycmlkZSBpdC5cbiAgY29uc3QgdGltZW91dCA9IG9wdGlvbnMudGltZW91dCB8fCA3MDAwMDtcblxuICBjb25zdCBmYWlsQWZ0ZXJIYW5kbGUgPSBmYWlsQWZ0ZXIodGltZW91dCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICBwb3N0SlNPTihcbiAgICAgIHVybCxcbiAgICAgIGJvZHksXG4gICAgICBoZWFkZXJzLFxuICAgICAgZnVuY3Rpb25zSW5zdGFuY2UuZmV0Y2hJbXBsLFxuICAgICAgZnVuY3Rpb25zSW5zdGFuY2VcbiAgICApLFxuICAgIGZhaWxBZnRlckhhbmRsZS5wcm9taXNlLFxuICAgIGZ1bmN0aW9uc0luc3RhbmNlLmNhbmNlbEFsbFJlcXVlc3RzXG4gIF0pO1xuXG4gIC8vIEFsd2F5cyBjbGVhciB0aGUgZmFpbEFmdGVyIHRpbWVvdXRcbiAgZmFpbEFmdGVySGFuZGxlLmNhbmNlbCgpO1xuXG4gIC8vIElmIHNlcnZpY2Ugd2FzIGRlbGV0ZWQsIGludGVycnVwdGVkIHJlc3BvbnNlIHRocm93cyBhbiBlcnJvci5cbiAgaWYgKCFyZXNwb25zZSkge1xuICAgIHRocm93IG5ldyBGdW5jdGlvbnNFcnJvcihcbiAgICAgICdjYW5jZWxsZWQnLFxuICAgICAgJ0ZpcmViYXNlIEZ1bmN0aW9ucyBpbnN0YW5jZSB3YXMgZGVsZXRlZC4nXG4gICAgKTtcbiAgfVxuXG4gIC8vIENoZWNrIGZvciBhbiBlcnJvciBzdGF0dXMsIHJlZ2FyZGxlc3Mgb2YgaHR0cCBzdGF0dXMuXG4gIGNvbnN0IGVycm9yID0gX2Vycm9yRm9yUmVzcG9uc2UocmVzcG9uc2Uuc3RhdHVzLCByZXNwb25zZS5qc29uKTtcbiAgaWYgKGVycm9yKSB7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBpZiAoIXJlc3BvbnNlLmpzb24pIHtcbiAgICB0aHJvdyBuZXcgRnVuY3Rpb25zRXJyb3IoJ2ludGVybmFsJywgJ1Jlc3BvbnNlIGlzIG5vdCB2YWxpZCBKU09OIG9iamVjdC4nKTtcbiAgfVxuXG4gIGxldCByZXNwb25zZURhdGEgPSByZXNwb25zZS5qc29uLmRhdGE7XG4gIC8vIFRPRE8oa2xpbXQpOiBGb3IgcmlnaHQgbm93LCBhbGxvdyBcInJlc3VsdFwiIGluc3RlYWQgb2YgXCJkYXRhXCIsIGZvclxuICAvLyBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgaWYgKHR5cGVvZiByZXNwb25zZURhdGEgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmVzcG9uc2VEYXRhID0gcmVzcG9uc2UuanNvbi5yZXN1bHQ7XG4gIH1cbiAgaWYgKHR5cGVvZiByZXNwb25zZURhdGEgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gQ29uc2lkZXIgdGhlIHJlc3BvbnNlIG1hbGZvcm1lZC5cbiAgICB0aHJvdyBuZXcgRnVuY3Rpb25zRXJyb3IoJ2ludGVybmFsJywgJ1Jlc3BvbnNlIGlzIG1pc3NpbmcgZGF0YSBmaWVsZC4nKTtcbiAgfVxuXG4gIC8vIERlY29kZSBhbnkgc3BlY2lhbCB0eXBlcywgc3VjaCBhcyBkYXRlcywgaW4gdGhlIHJldHVybmVkIGRhdGEuXG4gIGNvbnN0IGRlY29kZWREYXRhID0gZGVjb2RlKHJlc3BvbnNlRGF0YSk7XG5cbiAgcmV0dXJuIHsgZGF0YTogZGVjb2RlZERhdGEgfTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIGNhbGxhYmxlIGZ1bmN0aW9uIGFzeW5jaHJvbm91c2x5IGFuZCByZXR1cm5zIGEgc3RyZWFtaW5nIHJlc3VsdC5cbiAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBjYWxsYWJsZSB0cmlnZ2VyLlxuICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gcGFzcyBhcyBwYXJhbXMgdG8gdGhlIGZ1bmN0aW9uLlxuICogQHBhcmFtIG9wdGlvbnMgU3RyZWFtaW5nIHJlcXVlc3Qgb3B0aW9ucy5cbiAqL1xuZnVuY3Rpb24gc3RyZWFtKFxuICBmdW5jdGlvbnNJbnN0YW5jZTogRnVuY3Rpb25zU2VydmljZSxcbiAgbmFtZTogc3RyaW5nLFxuICBkYXRhOiB1bmtub3duLFxuICBvcHRpb25zPzogSHR0cHNDYWxsYWJsZVN0cmVhbU9wdGlvbnNcbik6IFByb21pc2U8SHR0cHNDYWxsYWJsZVN0cmVhbVJlc3VsdD4ge1xuICBjb25zdCB1cmwgPSBmdW5jdGlvbnNJbnN0YW5jZS5fdXJsKG5hbWUpO1xuICByZXR1cm4gc3RyZWFtQXRVUkwoZnVuY3Rpb25zSW5zdGFuY2UsIHVybCwgZGF0YSwgb3B0aW9ucyB8fCB7fSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBjYWxsYWJsZSBmdW5jdGlvbiBhc3luY2hyb25vdXNseSBhbmQgcmV0dXJuIGEgc3RyZWFtaW5nIHJlc3VsdC5cbiAqIEBwYXJhbSB1cmwgVGhlIHVybCBvZiB0aGUgY2FsbGFibGUgdHJpZ2dlci5cbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIHBhc3MgYXMgcGFyYW1zIHRvIHRoZSBmdW5jdGlvbi5cbiAqIEBwYXJhbSBvcHRpb25zIFN0cmVhbWluZyByZXF1ZXN0IG9wdGlvbnMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHN0cmVhbUF0VVJMKFxuICBmdW5jdGlvbnNJbnN0YW5jZTogRnVuY3Rpb25zU2VydmljZSxcbiAgdXJsOiBzdHJpbmcsXG4gIGRhdGE6IHVua25vd24sXG4gIG9wdGlvbnM6IEh0dHBzQ2FsbGFibGVTdHJlYW1PcHRpb25zXG4pOiBQcm9taXNlPEh0dHBzQ2FsbGFibGVTdHJlYW1SZXN1bHQ+IHtcbiAgLy8gRW5jb2RlIGFueSBzcGVjaWFsIHR5cGVzLCBzdWNoIGFzIGRhdGVzLCBpbiB0aGUgaW5wdXQgZGF0YS5cbiAgZGF0YSA9IGVuY29kZShkYXRhKTtcbiAgY29uc3QgYm9keSA9IHsgZGF0YSB9O1xuICAvL1xuICAvLyBBZGQgYSBoZWFkZXIgZm9yIHRoZSBhdXRoVG9rZW4uXG4gIGNvbnN0IGhlYWRlcnMgPSBhd2FpdCBtYWtlQXV0aEhlYWRlcnMoZnVuY3Rpb25zSW5zdGFuY2UsIG9wdGlvbnMpO1xuICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAgaGVhZGVyc1snQWNjZXB0J10gPSAndGV4dC9ldmVudC1zdHJlYW0nO1xuXG4gIGxldCByZXNwb25zZTogUmVzcG9uc2U7XG4gIHRyeSB7XG4gICAgcmVzcG9uc2UgPSBhd2FpdCBmdW5jdGlvbnNJbnN0YW5jZS5mZXRjaEltcGwodXJsLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KGJvZHkpLFxuICAgICAgaGVhZGVycyxcbiAgICAgIHNpZ25hbDogb3B0aW9ucz8uc2lnbmFsLFxuICAgICAgY3JlZGVudGlhbHM6IGdldENyZWRlbnRpYWxzKGZ1bmN0aW9uc0luc3RhbmNlKVxuICAgIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBFcnJvciAmJiBlLm5hbWUgPT09ICdBYm9ydEVycm9yJykge1xuICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRnVuY3Rpb25zRXJyb3IoJ2NhbmNlbGxlZCcsICdSZXF1ZXN0IHdhcyBjYW5jZWxsZWQuJyk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkYXRhOiBQcm9taXNlLnJlamVjdChlcnJvciksXG4gICAgICAgIHN0cmVhbToge1xuICAgICAgICAgIFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBuZXh0KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBUaGlzIGNvdWxkIGJlIGFuIHVuaGFuZGxlZCBlcnJvciBvbiB0aGUgYmFja2VuZCwgb3IgaXQgY291bGQgYmUgYVxuICAgIC8vIG5ldHdvcmsgZXJyb3IuIFRoZXJlJ3Mgbm8gd2F5IHRvIGtub3csIHNpbmNlIGFuIHVuaGFuZGxlZCBlcnJvciBvbiB0aGVcbiAgICAvLyBiYWNrZW5kIHdpbGwgZmFpbCB0byBzZXQgdGhlIHByb3BlciBDT1JTIGhlYWRlciwgYW5kIHRodXMgd2lsbCBiZVxuICAgIC8vIHRyZWF0ZWQgYXMgYSBuZXR3b3JrIGVycm9yIGJ5IGZldGNoLlxuICAgIGNvbnN0IGVycm9yID0gX2Vycm9yRm9yUmVzcG9uc2UoMCwgbnVsbCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IFByb21pc2UucmVqZWN0KGVycm9yKSxcbiAgICAgIC8vIFJldHVybiBhbiBlbXB0eSBhc3luYyBpdGVyYXRvclxuICAgICAgc3RyZWFtOiB7XG4gICAgICAgIFtTeW1ib2wuYXN5bmNJdGVyYXRvcl0oKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5leHQoKSB7XG4gICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gIH1cbiAgbGV0IHJlc3VsdFJlc29sdmVyOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQ7XG4gIGxldCByZXN1bHRSZWplY3RlcjogKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZDtcbiAgY29uc3QgcmVzdWx0UHJvbWlzZSA9IG5ldyBQcm9taXNlPHVua25vd24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICByZXN1bHRSZXNvbHZlciA9IHJlc29sdmU7XG4gICAgcmVzdWx0UmVqZWN0ZXIgPSByZWplY3Q7XG4gIH0pO1xuICBvcHRpb25zPy5zaWduYWw/LmFkZEV2ZW50TGlzdGVuZXIoJ2Fib3J0JywgKCkgPT4ge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEZ1bmN0aW9uc0Vycm9yKCdjYW5jZWxsZWQnLCAnUmVxdWVzdCB3YXMgY2FuY2VsbGVkLicpO1xuICAgIHJlc3VsdFJlamVjdGVyKGVycm9yKTtcbiAgfSk7XG4gIGNvbnN0IHJlYWRlciA9IHJlc3BvbnNlLmJvZHkhLmdldFJlYWRlcigpO1xuICBjb25zdCByc3RyZWFtID0gY3JlYXRlUmVzcG9uc2VTdHJlYW0oXG4gICAgcmVhZGVyLFxuICAgIHJlc3VsdFJlc29sdmVyISxcbiAgICByZXN1bHRSZWplY3RlciEsXG4gICAgb3B0aW9ucz8uc2lnbmFsXG4gICk7XG4gIHJldHVybiB7XG4gICAgc3RyZWFtOiB7XG4gICAgICBbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCkge1xuICAgICAgICBjb25zdCBycmVhZGVyID0gcnN0cmVhbS5nZXRSZWFkZXIoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBhc3luYyBuZXh0KCkge1xuICAgICAgICAgICAgY29uc3QgeyB2YWx1ZSwgZG9uZSB9ID0gYXdhaXQgcnJlYWRlci5yZWFkKCk7XG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogdmFsdWUgYXMgdW5rbm93biwgZG9uZSB9O1xuICAgICAgICAgIH0sXG4gICAgICAgICAgYXN5bmMgcmV0dXJuKCkge1xuICAgICAgICAgICAgYXdhaXQgcnJlYWRlci5jYW5jZWwoKTtcbiAgICAgICAgICAgIHJldHVybiB7IGRvbmU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSxcbiAgICBkYXRhOiByZXN1bHRQcm9taXNlXG4gIH07XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIFJlYWRhYmxlU3RyZWFtIHRoYXQgcHJvY2Vzc2VzIGEgc3RyZWFtaW5nIHJlc3BvbnNlIGZyb20gYSBzdHJlYW1pbmdcbiAqIGNhbGxhYmxlIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBkYXRhIGluIHNlcnZlci1zZW50IGV2ZW50IGZvcm1hdC5cbiAqXG4gKiBAcGFyYW0gcmVhZGVyIFRoZSB1bmRlcmx5aW5nIHJlYWRlciBwcm92aWRpbmcgcmF3IHJlc3BvbnNlIGRhdGFcbiAqIEBwYXJhbSByZXN1bHRSZXNvbHZlciBDYWxsYmFjayB0byByZXNvbHZlIHRoZSBmaW5hbCByZXN1bHQgd2hlbiByZWNlaXZlZFxuICogQHBhcmFtIHJlc3VsdFJlamVjdGVyIENhbGxiYWNrIHRvIHJlamVjdCB3aXRoIGFuIGVycm9yIGlmIGVuY291bnRlcmVkXG4gKiBAcGFyYW0gc2lnbmFsIE9wdGlvbmFsIEFib3J0U2lnbmFsIHRvIGNhbmNlbCB0aGUgc3RyZWFtIHByb2Nlc3NpbmdcbiAqIEByZXR1cm5zIEEgUmVhZGFibGVTdHJlYW0gdGhhdCBlbWl0cyBkZWNvZGVkIG1lc3NhZ2VzIGZyb20gdGhlIHJlc3BvbnNlXG4gKlxuICogVGhlIHJldHVybmVkIFJlYWRhYmxlU3RyZWFtOlxuICogICAxLiBFbWl0cyBpbmRpdmlkdWFsIG1lc3NhZ2VzIHdoZW4gXCJtZXNzYWdlXCIgZGF0YSBpcyByZWNlaXZlZFxuICogICAyLiBSZXNvbHZlcyB3aXRoIHRoZSBmaW5hbCByZXN1bHQgd2hlbiBhIFwicmVzdWx0XCIgbWVzc2FnZSBpcyByZWNlaXZlZFxuICogICAzLiBSZWplY3RzIHdpdGggYW4gZXJyb3IgaWYgYW4gXCJlcnJvclwiIG1lc3NhZ2UgaXMgcmVjZWl2ZWRcbiAqL1xuZnVuY3Rpb24gY3JlYXRlUmVzcG9uc2VTdHJlYW0oXG4gIHJlYWRlcjogUmVhZGFibGVTdHJlYW1EZWZhdWx0UmVhZGVyPFVpbnQ4QXJyYXk+LFxuICByZXN1bHRSZXNvbHZlcjogKHZhbHVlOiB1bmtub3duKSA9PiB2b2lkLFxuICByZXN1bHRSZWplY3RlcjogKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZCxcbiAgc2lnbmFsPzogQWJvcnRTaWduYWxcbik6IFJlYWRhYmxlU3RyZWFtPHVua25vd24+IHtcbiAgY29uc3QgcHJvY2Vzc0xpbmUgPSAoXG4gICAgbGluZTogc3RyaW5nLFxuICAgIGNvbnRyb2xsZXI6IFJlYWRhYmxlU3RyZWFtRGVmYXVsdENvbnRyb2xsZXJcbiAgKTogdm9pZCA9PiB7XG4gICAgY29uc3QgbWF0Y2ggPSBsaW5lLm1hdGNoKHJlc3BvbnNlTGluZVJFKTtcbiAgICAvLyBpZ25vcmUgYWxsIG90aGVyIGxpbmVzIChuZXdsaW5lLCBjb21tZW50cywgZXRjLilcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRhdGEgPSBtYXRjaFsxXTtcbiAgICB0cnkge1xuICAgICAgY29uc3QganNvbkRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgaWYgKCdyZXN1bHQnIGluIGpzb25EYXRhKSB7XG4gICAgICAgIHJlc3VsdFJlc29sdmVyKGRlY29kZShqc29uRGF0YS5yZXN1bHQpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCdtZXNzYWdlJyBpbiBqc29uRGF0YSkge1xuICAgICAgICBjb250cm9sbGVyLmVucXVldWUoZGVjb2RlKGpzb25EYXRhLm1lc3NhZ2UpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCdlcnJvcicgaW4ganNvbkRhdGEpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSBfZXJyb3JGb3JSZXNwb25zZSgwLCBqc29uRGF0YSk7XG4gICAgICAgIGNvbnRyb2xsZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICByZXN1bHRSZWplY3RlcihlcnJvcik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRnVuY3Rpb25zRXJyb3IpIHtcbiAgICAgICAgY29udHJvbGxlci5lcnJvcihlcnJvcik7XG4gICAgICAgIHJlc3VsdFJlamVjdGVyKGVycm9yKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gaWdub3JlIG90aGVyIHBhcnNpbmcgZXJyb3JzXG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcbiAgcmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbSh7XG4gICAgc3RhcnQoY29udHJvbGxlcikge1xuICAgICAgbGV0IGN1cnJlbnRUZXh0ID0gJyc7XG4gICAgICByZXR1cm4gcHVtcCgpO1xuICAgICAgYXN5bmMgZnVuY3Rpb24gcHVtcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IEZ1bmN0aW9uc0Vycm9yKFxuICAgICAgICAgICAgJ2NhbmNlbGxlZCcsXG4gICAgICAgICAgICAnUmVxdWVzdCB3YXMgY2FuY2VsbGVkJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29udHJvbGxlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgcmVzdWx0UmVqZWN0ZXIoZXJyb3IpO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHsgdmFsdWUsIGRvbmUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50VGV4dC50cmltKCkpIHtcbiAgICAgICAgICAgICAgcHJvY2Vzc0xpbmUoY3VycmVudFRleHQudHJpbSgpLCBjb250cm9sbGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRnVuY3Rpb25zRXJyb3IoXG4gICAgICAgICAgICAgICdjYW5jZWxsZWQnLFxuICAgICAgICAgICAgICAnUmVxdWVzdCB3YXMgY2FuY2VsbGVkJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnRyb2xsZXIuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgcmVzdWx0UmVqZWN0ZXIoZXJyb3IpO1xuICAgICAgICAgICAgYXdhaXQgcmVhZGVyLmNhbmNlbCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjdXJyZW50VGV4dCArPSBkZWNvZGVyLmRlY29kZSh2YWx1ZSwgeyBzdHJlYW06IHRydWUgfSk7XG4gICAgICAgICAgY29uc3QgbGluZXMgPSBjdXJyZW50VGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgICAgY3VycmVudFRleHQgPSBsaW5lcy5wb3AoKSB8fCAnJztcbiAgICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgICAgICAgIGlmIChsaW5lLnRyaW0oKSkge1xuICAgICAgICAgICAgICBwcm9jZXNzTGluZShsaW5lLnRyaW0oKSwgY29udHJvbGxlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBwdW1wKCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc3QgZnVuY3Rpb25zRXJyb3IgPVxuICAgICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBGdW5jdGlvbnNFcnJvclxuICAgICAgICAgICAgICA/IGVycm9yXG4gICAgICAgICAgICAgIDogX2Vycm9yRm9yUmVzcG9uc2UoMCwgbnVsbCk7XG4gICAgICAgICAgY29udHJvbGxlci5lcnJvcihmdW5jdGlvbnNFcnJvcik7XG4gICAgICAgICAgcmVzdWx0UmVqZWN0ZXIoZnVuY3Rpb25zRXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBjYW5jZWwoKSB7XG4gICAgICByZXR1cm4gcmVhZGVyLmNhbmNlbCgpO1xuICAgIH1cbiAgfSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgX3JlZ2lzdGVyQ29tcG9uZW50LCByZWdpc3RlclZlcnNpb24gfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IEZ1bmN0aW9uc1NlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2UnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRUeXBlLFxuICBDb21wb25lbnRDb250YWluZXIsXG4gIEluc3RhbmNlRmFjdG9yeVxufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IEZVTkNUSU9OU19UWVBFIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgRmlyZWJhc2VBdXRoSW50ZXJuYWxOYW1lIH0gZnJvbSAnQGZpcmViYXNlL2F1dGgtaW50ZXJvcC10eXBlcyc7XG5pbXBvcnQgeyBBcHBDaGVja0ludGVybmFsQ29tcG9uZW50TmFtZSB9IGZyb20gJ0BmaXJlYmFzZS9hcHAtY2hlY2staW50ZXJvcC10eXBlcyc7XG5pbXBvcnQgeyBNZXNzYWdpbmdJbnRlcm5hbENvbXBvbmVudE5hbWUgfSBmcm9tICdAZmlyZWJhc2UvbWVzc2FnaW5nLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHsgbmFtZSwgdmVyc2lvbiB9IGZyb20gJy4uL3BhY2thZ2UuanNvbic7XG5cbmNvbnN0IEFVVEhfSU5URVJOQUxfTkFNRTogRmlyZWJhc2VBdXRoSW50ZXJuYWxOYW1lID0gJ2F1dGgtaW50ZXJuYWwnO1xuY29uc3QgQVBQX0NIRUNLX0lOVEVSTkFMX05BTUU6IEFwcENoZWNrSW50ZXJuYWxDb21wb25lbnROYW1lID1cbiAgJ2FwcC1jaGVjay1pbnRlcm5hbCc7XG5jb25zdCBNRVNTQUdJTkdfSU5URVJOQUxfTkFNRTogTWVzc2FnaW5nSW50ZXJuYWxDb21wb25lbnROYW1lID1cbiAgJ21lc3NhZ2luZy1pbnRlcm5hbCc7XG5cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckZ1bmN0aW9ucyh2YXJpYW50Pzogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGZhY3Rvcnk6IEluc3RhbmNlRmFjdG9yeTwnZnVuY3Rpb25zJz4gPSAoXG4gICAgY29udGFpbmVyOiBDb21wb25lbnRDb250YWluZXIsXG4gICAgeyBpbnN0YW5jZUlkZW50aWZpZXI6IHJlZ2lvbk9yQ3VzdG9tRG9tYWluIH1cbiAgKSA9PiB7XG4gICAgLy8gRGVwZW5kZW5jaWVzXG4gICAgY29uc3QgYXBwID0gY29udGFpbmVyLmdldFByb3ZpZGVyKCdhcHAnKS5nZXRJbW1lZGlhdGUoKTtcbiAgICBjb25zdCBhdXRoUHJvdmlkZXIgPSBjb250YWluZXIuZ2V0UHJvdmlkZXIoQVVUSF9JTlRFUk5BTF9OQU1FKTtcbiAgICBjb25zdCBtZXNzYWdpbmdQcm92aWRlciA9IGNvbnRhaW5lci5nZXRQcm92aWRlcihNRVNTQUdJTkdfSU5URVJOQUxfTkFNRSk7XG4gICAgY29uc3QgYXBwQ2hlY2tQcm92aWRlciA9IGNvbnRhaW5lci5nZXRQcm92aWRlcihBUFBfQ0hFQ0tfSU5URVJOQUxfTkFNRSk7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIHJldHVybiBuZXcgRnVuY3Rpb25zU2VydmljZShcbiAgICAgIGFwcCxcbiAgICAgIGF1dGhQcm92aWRlcixcbiAgICAgIG1lc3NhZ2luZ1Byb3ZpZGVyLFxuICAgICAgYXBwQ2hlY2tQcm92aWRlcixcbiAgICAgIHJlZ2lvbk9yQ3VzdG9tRG9tYWluXG4gICAgKTtcbiAgfTtcblxuICBfcmVnaXN0ZXJDb21wb25lbnQoXG4gICAgbmV3IENvbXBvbmVudChcbiAgICAgIEZVTkNUSU9OU19UWVBFLFxuICAgICAgZmFjdG9yeSxcbiAgICAgIENvbXBvbmVudFR5cGUuUFVCTElDXG4gICAgKS5zZXRNdWx0aXBsZUluc3RhbmNlcyh0cnVlKVxuICApO1xuXG4gIHJlZ2lzdGVyVmVyc2lvbihuYW1lLCB2ZXJzaW9uLCB2YXJpYW50KTtcbiAgLy8gQlVJTERfVEFSR0VUIHdpbGwgYmUgcmVwbGFjZWQgYnkgdmFsdWVzIGxpa2UgZXNtLCBjanMsIGV0YyBkdXJpbmcgdGhlIGNvbXBpbGF0aW9uXG4gIHJlZ2lzdGVyVmVyc2lvbihuYW1lLCB2ZXJzaW9uLCAnX19CVUlMRF9UQVJHRVRfXycpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IF9nZXRQcm92aWRlciwgRmlyZWJhc2VBcHAsIGdldEFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgRlVOQ1RJT05TX1RZUEUgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbmltcG9ydCB7IFByb3ZpZGVyIH0gZnJvbSAnQGZpcmViYXNlL2NvbXBvbmVudCc7XG5pbXBvcnQgeyBGdW5jdGlvbnMsIEh0dHBzQ2FsbGFibGVPcHRpb25zLCBIdHRwc0NhbGxhYmxlIH0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHtcbiAgRnVuY3Rpb25zU2VydmljZSxcbiAgREVGQVVMVF9SRUdJT04sXG4gIGNvbm5lY3RGdW5jdGlvbnNFbXVsYXRvciBhcyBfY29ubmVjdEZ1bmN0aW9uc0VtdWxhdG9yLFxuICBodHRwc0NhbGxhYmxlIGFzIF9odHRwc0NhbGxhYmxlLFxuICBodHRwc0NhbGxhYmxlRnJvbVVSTCBhcyBfaHR0cHNDYWxsYWJsZUZyb21VUkxcbn0gZnJvbSAnLi9zZXJ2aWNlJztcbmltcG9ydCB7XG4gIGdldE1vZHVsYXJJbnN0YW5jZSxcbiAgZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdG5hbWVBbmRQb3J0XG59IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IHsgRnVuY3Rpb25zRXJyb3IgfSBmcm9tICcuL2Vycm9yJztcbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLXR5cGVzJztcblxuLyoqXG4gKiBSZXR1cm5zIGEge0BsaW5rIEZ1bmN0aW9uc30gaW5zdGFuY2UgZm9yIHRoZSBnaXZlbiBhcHAuXG4gKiBAcGFyYW0gYXBwIC0gVGhlIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlQXBwfSB0byB1c2UuXG4gKiBAcGFyYW0gcmVnaW9uT3JDdXN0b21Eb21haW4gLSBvbmUgb2Y6XG4gKiAgIGEpIFRoZSByZWdpb24gdGhlIGNhbGxhYmxlIGZ1bmN0aW9ucyBhcmUgbG9jYXRlZCBpbiAoZXg6IHVzLWNlbnRyYWwxKVxuICogICBiKSBBIGN1c3RvbSBkb21haW4gaG9zdGluZyB0aGUgY2FsbGFibGUgZnVuY3Rpb25zIChleDogaHR0cHM6Ly9teWRvbWFpbi5jb20pXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRGdW5jdGlvbnMoXG4gIGFwcDogRmlyZWJhc2VBcHAgPSBnZXRBcHAoKSxcbiAgcmVnaW9uT3JDdXN0b21Eb21haW46IHN0cmluZyA9IERFRkFVTFRfUkVHSU9OXG4pOiBGdW5jdGlvbnMge1xuICAvLyBEZXBlbmRlbmNpZXNcbiAgY29uc3QgZnVuY3Rpb25zUHJvdmlkZXI6IFByb3ZpZGVyPCdmdW5jdGlvbnMnPiA9IF9nZXRQcm92aWRlcihcbiAgICBnZXRNb2R1bGFySW5zdGFuY2UoYXBwKSxcbiAgICBGVU5DVElPTlNfVFlQRVxuICApO1xuICBjb25zdCBmdW5jdGlvbnNJbnN0YW5jZSA9IGZ1bmN0aW9uc1Byb3ZpZGVyLmdldEltbWVkaWF0ZSh7XG4gICAgaWRlbnRpZmllcjogcmVnaW9uT3JDdXN0b21Eb21haW5cbiAgfSk7XG4gIGNvbnN0IGVtdWxhdG9yID0gZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdG5hbWVBbmRQb3J0KCdmdW5jdGlvbnMnKTtcbiAgaWYgKGVtdWxhdG9yKSB7XG4gICAgY29ubmVjdEZ1bmN0aW9uc0VtdWxhdG9yKGZ1bmN0aW9uc0luc3RhbmNlLCAuLi5lbXVsYXRvcik7XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uc0luc3RhbmNlO1xufVxuXG4vKipcbiAqIE1vZGlmeSB0aGlzIGluc3RhbmNlIHRvIGNvbW11bmljYXRlIHdpdGggdGhlIENsb3VkIEZ1bmN0aW9ucyBlbXVsYXRvci5cbiAqXG4gKiBOb3RlOiB0aGlzIG11c3QgYmUgY2FsbGVkIGJlZm9yZSB0aGlzIGluc3RhbmNlIGhhcyBiZWVuIHVzZWQgdG8gZG8gYW55IG9wZXJhdGlvbnMuXG4gKlxuICogQHBhcmFtIGhvc3QgLSBUaGUgZW11bGF0b3IgaG9zdCAoZXg6IGxvY2FsaG9zdClcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIGVtdWxhdG9yIHBvcnQgKGV4OiA1MDAxKVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29ubmVjdEZ1bmN0aW9uc0VtdWxhdG9yKFxuICBmdW5jdGlvbnNJbnN0YW5jZTogRnVuY3Rpb25zLFxuICBob3N0OiBzdHJpbmcsXG4gIHBvcnQ6IG51bWJlclxuKTogdm9pZCB7XG4gIF9jb25uZWN0RnVuY3Rpb25zRW11bGF0b3IoXG4gICAgZ2V0TW9kdWxhckluc3RhbmNlPEZ1bmN0aW9uc1NlcnZpY2U+KGZ1bmN0aW9uc0luc3RhbmNlIGFzIEZ1bmN0aW9uc1NlcnZpY2UpLFxuICAgIGhvc3QsXG4gICAgcG9ydFxuICApO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIGNhbGxhYmxlIEhUVFBTIHRyaWdnZXIgd2l0aCB0aGUgZ2l2ZW4gbmFtZS5cbiAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRyaWdnZXIuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBodHRwc0NhbGxhYmxlPFxuICBSZXF1ZXN0RGF0YSA9IHVua25vd24sXG4gIFJlc3BvbnNlRGF0YSA9IHVua25vd24sXG4gIFN0cmVhbURhdGEgPSB1bmtub3duXG4+KFxuICBmdW5jdGlvbnNJbnN0YW5jZTogRnVuY3Rpb25zLFxuICBuYW1lOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBIdHRwc0NhbGxhYmxlT3B0aW9uc1xuKTogSHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPiB7XG4gIHJldHVybiBfaHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPihcbiAgICBnZXRNb2R1bGFySW5zdGFuY2U8RnVuY3Rpb25zU2VydmljZT4oZnVuY3Rpb25zSW5zdGFuY2UgYXMgRnVuY3Rpb25zU2VydmljZSksXG4gICAgbmFtZSxcbiAgICBvcHRpb25zXG4gICk7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgY2FsbGFibGUgSFRUUFMgdHJpZ2dlciB3aXRoIHRoZSBzcGVjaWZpZWQgdXJsLlxuICogQHBhcmFtIHVybCAtIFRoZSB1cmwgb2YgdGhlIHRyaWdnZXIuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBodHRwc0NhbGxhYmxlRnJvbVVSTDxcbiAgUmVxdWVzdERhdGEgPSB1bmtub3duLFxuICBSZXNwb25zZURhdGEgPSB1bmtub3duLFxuICBTdHJlYW1EYXRhID0gdW5rbm93blxuPihcbiAgZnVuY3Rpb25zSW5zdGFuY2U6IEZ1bmN0aW9ucyxcbiAgdXJsOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBIdHRwc0NhbGxhYmxlT3B0aW9uc1xuKTogSHR0cHNDYWxsYWJsZTxSZXF1ZXN0RGF0YSwgUmVzcG9uc2VEYXRhLCBTdHJlYW1EYXRhPiB7XG4gIHJldHVybiBfaHR0cHNDYWxsYWJsZUZyb21VUkw8UmVxdWVzdERhdGEsIFJlc3BvbnNlRGF0YSwgU3RyZWFtRGF0YT4oXG4gICAgZ2V0TW9kdWxhckluc3RhbmNlPEZ1bmN0aW9uc1NlcnZpY2U+KGZ1bmN0aW9uc0luc3RhbmNlIGFzIEZ1bmN0aW9uc1NlcnZpY2UpLFxuICAgIHVybCxcbiAgICBvcHRpb25zXG4gICk7XG59XG4iLCAiLyoqXG4gKiBDbG91ZCBGdW5jdGlvbnMgZm9yIEZpcmViYXNlXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cblxuLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IHJlZ2lzdGVyRnVuY3Rpb25zIH0gZnJvbSAnLi9jb25maWcnO1xuXG5leHBvcnQgKiBmcm9tICcuL2FwaSc7XG5leHBvcnQgKiBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5cbnJlZ2lzdGVyRnVuY3Rpb25zKCk7XG4iLCAiZXhwb3J0ICogZnJvbSAnQGZpcmViYXNlL2Z1bmN0aW9ucyc7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5tanMubWFwXG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbi8qKlxuICogQGZpbGVvdmVydmlldyBDb25zdGFudHMgdXNlZCBpbiB0aGUgRmlyZWJhc2UgU3RvcmFnZSBsaWJyYXJ5LlxuICovXG5cbi8qKlxuICogRG9tYWluIG5hbWUgZm9yIGZpcmViYXNlIHN0b3JhZ2UuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0hPU1QgPSAnZmlyZWJhc2VzdG9yYWdlLmdvb2dsZWFwaXMuY29tJztcblxuLyoqXG4gKiBUaGUga2V5IGluIEZpcmViYXNlIGNvbmZpZyBqc29uIGZvciB0aGUgc3RvcmFnZSBidWNrZXQuXG4gKi9cbmV4cG9ydCBjb25zdCBDT05GSUdfU1RPUkFHRV9CVUNLRVRfS0VZID0gJ3N0b3JhZ2VCdWNrZXQnO1xuXG4vKipcbiAqIDIgbWludXRlc1xuICpcbiAqIFRoZSB0aW1lb3V0IGZvciBhbGwgb3BlcmF0aW9ucyBleGNlcHQgdXBsb2FkLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NQVhfT1BFUkFUSU9OX1JFVFJZX1RJTUUgPSAyICogNjAgKiAxMDAwO1xuXG4vKipcbiAqIDEwIG1pbnV0ZXNcbiAqXG4gKiBUaGUgdGltZW91dCBmb3IgdXBsb2FkLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NQVhfVVBMT0FEX1JFVFJZX1RJTUUgPSAxMCAqIDYwICogMTAwMDtcblxuLyoqXG4gKiAxIHNlY29uZFxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9NSU5fU0xFRVBfVElNRV9NSUxMSVMgPSAxMDAwO1xuXG4vKipcbiAqIFRoaXMgaXMgdGhlIHZhbHVlIG9mIE51bWJlci5NSU5fU0FGRV9JTlRFR0VSLCB3aGljaCBpcyBub3Qgd2VsbCBzdXBwb3J0ZWRcbiAqIGVub3VnaCBmb3IgdXMgdG8gdXNlIGl0IGRpcmVjdGx5LlxuICovXG5leHBvcnQgY29uc3QgTUlOX1NBRkVfSU5URUdFUiA9IC05MDA3MTk5MjU0NzQwOTkxO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEZpcmViYXNlRXJyb3IgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7IENPTkZJR19TVE9SQUdFX0JVQ0tFVF9LRVkgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbi8qKlxuICogQW4gZXJyb3IgcmV0dXJuZWQgYnkgdGhlIEZpcmViYXNlIFN0b3JhZ2UgU0RLLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgU3RvcmFnZUVycm9yIGV4dGVuZHMgRmlyZWJhc2VFcnJvciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Jhc2VNZXNzYWdlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBTdG9yZXMgY3VzdG9tIGVycm9yIGRhdGEgdW5pcXVlIHRvIHRoZSBgU3RvcmFnZUVycm9yYC5cbiAgICovXG4gIGN1c3RvbURhdGE6IHsgc2VydmVyUmVzcG9uc2U6IHN0cmluZyB8IG51bGwgfSA9IHsgc2VydmVyUmVzcG9uc2U6IG51bGwgfTtcblxuICAvKipcbiAgICogQHBhcmFtIGNvZGUgLSBBIGBTdG9yYWdlRXJyb3JDb2RlYCBzdHJpbmcgdG8gYmUgcHJlZml4ZWQgd2l0aCAnc3RvcmFnZS8nIGFuZFxuICAgKiAgYWRkZWQgdG8gdGhlIGVuZCBvZiB0aGUgbWVzc2FnZS5cbiAgICogQHBhcmFtIG1lc3NhZ2UgIC0gRXJyb3IgbWVzc2FnZS5cbiAgICogQHBhcmFtIHN0YXR1c18gLSBDb3JyZXNwb25kaW5nIEhUVFAgU3RhdHVzIENvZGVcbiAgICovXG4gIGNvbnN0cnVjdG9yKGNvZGU6IFN0b3JhZ2VFcnJvckNvZGUsIG1lc3NhZ2U6IHN0cmluZywgcHJpdmF0ZSBzdGF0dXNfID0gMCkge1xuICAgIHN1cGVyKFxuICAgICAgcHJlcGVuZENvZGUoY29kZSksXG4gICAgICBgRmlyZWJhc2UgU3RvcmFnZTogJHttZXNzYWdlfSAoJHtwcmVwZW5kQ29kZShjb2RlKX0pYFxuICAgICk7XG4gICAgdGhpcy5fYmFzZU1lc3NhZ2UgPSB0aGlzLm1lc3NhZ2U7XG4gICAgLy8gV2l0aG91dCB0aGlzLCBgaW5zdGFuY2VvZiBTdG9yYWdlRXJyb3JgLCBpbiB0ZXN0cyBmb3IgZXhhbXBsZSxcbiAgICAvLyByZXR1cm5zIGZhbHNlLlxuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBTdG9yYWdlRXJyb3IucHJvdG90eXBlKTtcbiAgfVxuXG4gIGdldCBzdGF0dXMoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0dXNfO1xuICB9XG5cbiAgc2V0IHN0YXR1cyhzdGF0dXM6IG51bWJlcikge1xuICAgIHRoaXMuc3RhdHVzXyA9IHN0YXR1cztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wYXJlcyBhIGBTdG9yYWdlRXJyb3JDb2RlYCBhZ2FpbnN0IHRoaXMgZXJyb3IncyBjb2RlLCBmaWx0ZXJpbmcgb3V0IHRoZSBwcmVmaXguXG4gICAqL1xuICBfY29kZUVxdWFscyhjb2RlOiBTdG9yYWdlRXJyb3JDb2RlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHByZXBlbmRDb2RlKGNvZGUpID09PSB0aGlzLmNvZGU7XG4gIH1cblxuICAvKipcbiAgICogT3B0aW9uYWwgcmVzcG9uc2UgbWVzc2FnZSB0aGF0IHdhcyBhZGRlZCBieSB0aGUgc2VydmVyLlxuICAgKi9cbiAgZ2V0IHNlcnZlclJlc3BvbnNlKCk6IG51bGwgfCBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmN1c3RvbURhdGEuc2VydmVyUmVzcG9uc2U7XG4gIH1cblxuICBzZXQgc2VydmVyUmVzcG9uc2Uoc2VydmVyUmVzcG9uc2U6IHN0cmluZyB8IG51bGwpIHtcbiAgICB0aGlzLmN1c3RvbURhdGEuc2VydmVyUmVzcG9uc2UgPSBzZXJ2ZXJSZXNwb25zZTtcbiAgICBpZiAodGhpcy5jdXN0b21EYXRhLnNlcnZlclJlc3BvbnNlKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBgJHt0aGlzLl9iYXNlTWVzc2FnZX1cXG4ke3RoaXMuY3VzdG9tRGF0YS5zZXJ2ZXJSZXNwb25zZX1gO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSB0aGlzLl9iYXNlTWVzc2FnZTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGVycm9ycyA9IHt9O1xuXG4vKipcbiAqIEBwdWJsaWNcbiAqIEVycm9yIGNvZGVzIHRoYXQgY2FuIGJlIGF0dGFjaGVkIHRvIGBTdG9yYWdlRXJyb3JgIG9iamVjdHMuXG4gKi9cbmV4cG9ydCBlbnVtIFN0b3JhZ2VFcnJvckNvZGUge1xuICAvLyBTaGFyZWQgYmV0d2VlbiBhbGwgcGxhdGZvcm1zXG4gIFVOS05PV04gPSAndW5rbm93bicsXG4gIE9CSkVDVF9OT1RfRk9VTkQgPSAnb2JqZWN0LW5vdC1mb3VuZCcsXG4gIEJVQ0tFVF9OT1RfRk9VTkQgPSAnYnVja2V0LW5vdC1mb3VuZCcsXG4gIFBST0pFQ1RfTk9UX0ZPVU5EID0gJ3Byb2plY3Qtbm90LWZvdW5kJyxcbiAgUVVPVEFfRVhDRUVERUQgPSAncXVvdGEtZXhjZWVkZWQnLFxuICBVTkFVVEhFTlRJQ0FURUQgPSAndW5hdXRoZW50aWNhdGVkJyxcbiAgVU5BVVRIT1JJWkVEID0gJ3VuYXV0aG9yaXplZCcsXG4gIFVOQVVUSE9SSVpFRF9BUFAgPSAndW5hdXRob3JpemVkLWFwcCcsXG4gIFJFVFJZX0xJTUlUX0VYQ0VFREVEID0gJ3JldHJ5LWxpbWl0LWV4Y2VlZGVkJyxcbiAgSU5WQUxJRF9DSEVDS1NVTSA9ICdpbnZhbGlkLWNoZWNrc3VtJyxcbiAgQ0FOQ0VMRUQgPSAnY2FuY2VsZWQnLFxuICAvLyBKUyBzcGVjaWZpY1xuICBJTlZBTElEX0VWRU5UX05BTUUgPSAnaW52YWxpZC1ldmVudC1uYW1lJyxcbiAgSU5WQUxJRF9VUkwgPSAnaW52YWxpZC11cmwnLFxuICBJTlZBTElEX0RFRkFVTFRfQlVDS0VUID0gJ2ludmFsaWQtZGVmYXVsdC1idWNrZXQnLFxuICBOT19ERUZBVUxUX0JVQ0tFVCA9ICduby1kZWZhdWx0LWJ1Y2tldCcsXG4gIENBTk5PVF9TTElDRV9CTE9CID0gJ2Nhbm5vdC1zbGljZS1ibG9iJyxcbiAgU0VSVkVSX0ZJTEVfV1JPTkdfU0laRSA9ICdzZXJ2ZXItZmlsZS13cm9uZy1zaXplJyxcbiAgTk9fRE9XTkxPQURfVVJMID0gJ25vLWRvd25sb2FkLXVybCcsXG4gIElOVkFMSURfQVJHVU1FTlQgPSAnaW52YWxpZC1hcmd1bWVudCcsXG4gIElOVkFMSURfQVJHVU1FTlRfQ09VTlQgPSAnaW52YWxpZC1hcmd1bWVudC1jb3VudCcsXG4gIEFQUF9ERUxFVEVEID0gJ2FwcC1kZWxldGVkJyxcbiAgSU5WQUxJRF9ST09UX09QRVJBVElPTiA9ICdpbnZhbGlkLXJvb3Qtb3BlcmF0aW9uJyxcbiAgSU5WQUxJRF9GT1JNQVQgPSAnaW52YWxpZC1mb3JtYXQnLFxuICBJTlRFUk5BTF9FUlJPUiA9ICdpbnRlcm5hbC1lcnJvcicsXG4gIFVOU1VQUE9SVEVEX0VOVklST05NRU5UID0gJ3Vuc3VwcG9ydGVkLWVudmlyb25tZW50J1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGVuZENvZGUoY29kZTogU3RvcmFnZUVycm9yQ29kZSk6IHN0cmluZyB7XG4gIHJldHVybiAnc3RvcmFnZS8nICsgY29kZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVua25vd24oKTogU3RvcmFnZUVycm9yIHtcbiAgY29uc3QgbWVzc2FnZSA9XG4gICAgJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQsIHBsZWFzZSBjaGVjayB0aGUgZXJyb3IgcGF5bG9hZCBmb3IgJyArXG4gICAgJ3NlcnZlciByZXNwb25zZS4nO1xuICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcihTdG9yYWdlRXJyb3JDb2RlLlVOS05PV04sIG1lc3NhZ2UpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0Tm90Rm91bmQocGF0aDogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgIFwiT2JqZWN0ICdcIiArIHBhdGggKyBcIicgZG9lcyBub3QgZXhpc3QuXCJcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1Y2tldE5vdEZvdW5kKGJ1Y2tldDogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5CVUNLRVRfTk9UX0ZPVU5ELFxuICAgIFwiQnVja2V0ICdcIiArIGJ1Y2tldCArIFwiJyBkb2VzIG5vdCBleGlzdC5cIlxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJvamVjdE5vdEZvdW5kKHByb2plY3Q6IHN0cmluZyk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuUFJPSkVDVF9OT1RfRk9VTkQsXG4gICAgXCJQcm9qZWN0ICdcIiArIHByb2plY3QgKyBcIicgZG9lcyBub3QgZXhpc3QuXCJcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHF1b3RhRXhjZWVkZWQoYnVja2V0OiBzdHJpbmcpOiBTdG9yYWdlRXJyb3Ige1xuICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcihcbiAgICBTdG9yYWdlRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVELFxuICAgIFwiUXVvdGEgZm9yIGJ1Y2tldCAnXCIgK1xuICAgICAgYnVja2V0ICtcbiAgICAgIFwiJyBleGNlZWRlZCwgcGxlYXNlIHZpZXcgcXVvdGEgb24gXCIgK1xuICAgICAgJ2h0dHBzOi8vZmlyZWJhc2UuZ29vZ2xlLmNvbS9wcmljaW5nLy4nXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bmF1dGhlbnRpY2F0ZWQoKTogU3RvcmFnZUVycm9yIHtcbiAgY29uc3QgbWVzc2FnZSA9XG4gICAgJ1VzZXIgaXMgbm90IGF1dGhlbnRpY2F0ZWQsIHBsZWFzZSBhdXRoZW50aWNhdGUgdXNpbmcgRmlyZWJhc2UgJyArXG4gICAgJ0F1dGhlbnRpY2F0aW9uIGFuZCB0cnkgYWdhaW4uJztcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoU3RvcmFnZUVycm9yQ29kZS5VTkFVVEhFTlRJQ0FURUQsIG1lc3NhZ2UpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5hdXRob3JpemVkQXBwKCk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuVU5BVVRIT1JJWkVEX0FQUCxcbiAgICAnVGhpcyBhcHAgZG9lcyBub3QgaGF2ZSBwZXJtaXNzaW9uIHRvIGFjY2VzcyBGaXJlYmFzZSBTdG9yYWdlIG9uIHRoaXMgcHJvamVjdC4nXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bmF1dGhvcml6ZWQocGF0aDogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5VTkFVVEhPUklaRUQsXG4gICAgXCJVc2VyIGRvZXMgbm90IGhhdmUgcGVybWlzc2lvbiB0byBhY2Nlc3MgJ1wiICsgcGF0aCArIFwiJy5cIlxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmV0cnlMaW1pdEV4Y2VlZGVkKCk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuUkVUUllfTElNSVRfRVhDRUVERUQsXG4gICAgJ01heCByZXRyeSB0aW1lIGZvciBvcGVyYXRpb24gZXhjZWVkZWQsIHBsZWFzZSB0cnkgYWdhaW4uJ1xuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW52YWxpZENoZWNrc3VtKFxuICBwYXRoOiBzdHJpbmcsXG4gIGNoZWNrc3VtOiBzdHJpbmcsXG4gIGNhbGN1bGF0ZWQ6IHN0cmluZ1xuKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5JTlZBTElEX0NIRUNLU1VNLFxuICAgIFwiVXBsb2FkZWQvZG93bmxvYWRlZCBvYmplY3QgJ1wiICtcbiAgICAgIHBhdGggK1xuICAgICAgXCInIGhhcyBjaGVja3N1bSAnXCIgK1xuICAgICAgY2hlY2tzdW0gK1xuICAgICAgXCInIHdoaWNoIGRvZXMgbm90IG1hdGNoICdcIiArXG4gICAgICBjYWxjdWxhdGVkICtcbiAgICAgIFwiJy4gUGxlYXNlIHJldHJ5IHRoZSB1cGxvYWQvZG93bmxvYWQuXCJcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbmNlbGVkKCk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuQ0FOQ0VMRUQsXG4gICAgJ1VzZXIgY2FuY2VsZWQgdGhlIHVwbG9hZC9kb3dubG9hZC4nXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZhbGlkRXZlbnROYW1lKG5hbWU6IHN0cmluZyk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuSU5WQUxJRF9FVkVOVF9OQU1FLFxuICAgIFwiSW52YWxpZCBldmVudCBuYW1lICdcIiArIG5hbWUgKyBcIicuXCJcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGludmFsaWRVcmwodXJsOiBzdHJpbmcpOiBTdG9yYWdlRXJyb3Ige1xuICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcihcbiAgICBTdG9yYWdlRXJyb3JDb2RlLklOVkFMSURfVVJMLFxuICAgIFwiSW52YWxpZCBVUkwgJ1wiICsgdXJsICsgXCInLlwiXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZhbGlkRGVmYXVsdEJ1Y2tldChidWNrZXQ6IHN0cmluZyk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuSU5WQUxJRF9ERUZBVUxUX0JVQ0tFVCxcbiAgICBcIkludmFsaWQgZGVmYXVsdCBidWNrZXQgJ1wiICsgYnVja2V0ICsgXCInLlwiXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBub0RlZmF1bHRCdWNrZXQoKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5OT19ERUZBVUxUX0JVQ0tFVCxcbiAgICAnTm8gZGVmYXVsdCBidWNrZXQgJyArXG4gICAgICBcImZvdW5kLiBEaWQgeW91IHNldCB0aGUgJ1wiICtcbiAgICAgIENPTkZJR19TVE9SQUdFX0JVQ0tFVF9LRVkgK1xuICAgICAgXCInIHByb3BlcnR5IHdoZW4gaW5pdGlhbGl6aW5nIHRoZSBhcHA/XCJcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbm5vdFNsaWNlQmxvYigpOiBTdG9yYWdlRXJyb3Ige1xuICByZXR1cm4gbmV3IFN0b3JhZ2VFcnJvcihcbiAgICBTdG9yYWdlRXJyb3JDb2RlLkNBTk5PVF9TTElDRV9CTE9CLFxuICAgICdDYW5ub3Qgc2xpY2UgYmxvYiBmb3IgdXBsb2FkLiBQbGVhc2UgcmV0cnkgdGhlIHVwbG9hZC4nXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXJ2ZXJGaWxlV3JvbmdTaXplKCk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuU0VSVkVSX0ZJTEVfV1JPTkdfU0laRSxcbiAgICAnU2VydmVyIHJlY29yZGVkIGluY29ycmVjdCB1cGxvYWQgZmlsZSBzaXplLCBwbGVhc2UgcmV0cnkgdGhlIHVwbG9hZC4nXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBub0Rvd25sb2FkVVJMKCk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuTk9fRE9XTkxPQURfVVJMLFxuICAgICdUaGUgZ2l2ZW4gZmlsZSBkb2VzIG5vdCBoYXZlIGFueSBkb3dubG9hZCBVUkxzLidcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1pc3NpbmdQb2x5RmlsbChwb2x5RmlsbDogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5VTlNVUFBPUlRFRF9FTlZJUk9OTUVOVCxcbiAgICBgJHtwb2x5RmlsbH0gaXMgbWlzc2luZy4gTWFrZSBzdXJlIHRvIGluc3RhbGwgdGhlIHJlcXVpcmVkIHBvbHlmaWxscy4gU2VlIGh0dHBzOi8vZmlyZWJhc2UuZ29vZ2xlLmNvbS9kb2NzL3dlYi9lbnZpcm9ubWVudHMtanMtc2RrI3BvbHlmaWxscyBmb3IgbW9yZSBpbmZvcm1hdGlvbi5gXG4gICk7XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnZhbGlkQXJndW1lbnQobWVzc2FnZTogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoU3RvcmFnZUVycm9yQ29kZS5JTlZBTElEX0FSR1VNRU5ULCBtZXNzYWdlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGludmFsaWRBcmd1bWVudENvdW50KFxuICBhcmdNaW46IG51bWJlcixcbiAgYXJnTWF4OiBudW1iZXIsXG4gIGZuTmFtZTogc3RyaW5nLFxuICByZWFsOiBudW1iZXJcbik6IFN0b3JhZ2VFcnJvciB7XG4gIGxldCBjb3VudFBhcnQ7XG4gIGxldCBwbHVyYWw7XG4gIGlmIChhcmdNaW4gPT09IGFyZ01heCkge1xuICAgIGNvdW50UGFydCA9IGFyZ01pbjtcbiAgICBwbHVyYWwgPSBhcmdNaW4gPT09IDEgPyAnYXJndW1lbnQnIDogJ2FyZ3VtZW50cyc7XG4gIH0gZWxzZSB7XG4gICAgY291bnRQYXJ0ID0gJ2JldHdlZW4gJyArIGFyZ01pbiArICcgYW5kICcgKyBhcmdNYXg7XG4gICAgcGx1cmFsID0gJ2FyZ3VtZW50cyc7XG4gIH1cbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5JTlZBTElEX0FSR1VNRU5UX0NPVU5ULFxuICAgICdJbnZhbGlkIGFyZ3VtZW50IGNvdW50IGluIGAnICtcbiAgICAgIGZuTmFtZSArXG4gICAgICAnYDogRXhwZWN0ZWQgJyArXG4gICAgICBjb3VudFBhcnQgK1xuICAgICAgJyAnICtcbiAgICAgIHBsdXJhbCArXG4gICAgICAnLCByZWNlaXZlZCAnICtcbiAgICAgIHJlYWwgK1xuICAgICAgJy4nXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBEZWxldGVkKCk6IFN0b3JhZ2VFcnJvciB7XG4gIHJldHVybiBuZXcgU3RvcmFnZUVycm9yKFxuICAgIFN0b3JhZ2VFcnJvckNvZGUuQVBQX0RFTEVURUQsXG4gICAgJ1RoZSBGaXJlYmFzZSBhcHAgd2FzIGRlbGV0ZWQuJ1xuICApO1xufVxuXG4vKipcbiAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbiB0aGF0IHdhcyBpbnZhbGlkLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gaW52YWxpZFJvb3RPcGVyYXRpb24obmFtZTogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5JTlZBTElEX1JPT1RfT1BFUkFUSU9OLFxuICAgIFwiVGhlIG9wZXJhdGlvbiAnXCIgK1xuICAgICAgbmFtZSArXG4gICAgICBcIicgY2Fubm90IGJlIHBlcmZvcm1lZCBvbiBhIHJvb3QgcmVmZXJlbmNlLCBjcmVhdGUgYSBub24tcm9vdCBcIiArXG4gICAgICBcInJlZmVyZW5jZSB1c2luZyBjaGlsZCwgc3VjaCBhcyAuY2hpbGQoJ2ZpbGUucG5nJykuXCJcbiAgKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gZm9ybWF0IC0gVGhlIGZvcm1hdCB0aGF0IHdhcyBub3QgdmFsaWQuXG4gKiBAcGFyYW0gbWVzc2FnZSAtIEEgbWVzc2FnZSBkZXNjcmliaW5nIHRoZSBmb3JtYXQgdmlvbGF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW52YWxpZEZvcm1hdChmb3JtYXQ6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgcmV0dXJuIG5ldyBTdG9yYWdlRXJyb3IoXG4gICAgU3RvcmFnZUVycm9yQ29kZS5JTlZBTElEX0ZPUk1BVCxcbiAgICBcIlN0cmluZyBkb2VzIG5vdCBtYXRjaCBmb3JtYXQgJ1wiICsgZm9ybWF0ICsgXCInOiBcIiArIG1lc3NhZ2VcbiAgKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gbWVzc2FnZSAtIEEgbWVzc2FnZSBkZXNjcmliaW5nIHRoZSBpbnRlcm5hbCBlcnJvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuc3VwcG9ydGVkRW52aXJvbm1lbnQobWVzc2FnZTogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgdGhyb3cgbmV3IFN0b3JhZ2VFcnJvcihTdG9yYWdlRXJyb3JDb2RlLlVOU1VQUE9SVEVEX0VOVklST05NRU5ULCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0gbWVzc2FnZSAtIEEgbWVzc2FnZSBkZXNjcmliaW5nIHRoZSBpbnRlcm5hbCBlcnJvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVybmFsRXJyb3IobWVzc2FnZTogc3RyaW5nKTogU3RvcmFnZUVycm9yIHtcbiAgdGhyb3cgbmV3IFN0b3JhZ2VFcnJvcihcbiAgICBTdG9yYWdlRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuICAgICdJbnRlcm5hbCBlcnJvcjogJyArIG1lc3NhZ2VcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgRnVuY3Rpb25hbGl0eSByZWxhdGVkIHRvIHRoZSBwYXJzaW5nL2NvbXBvc2l0aW9uIG9mIGJ1Y2tldC9cbiAqIG9iamVjdCBsb2NhdGlvbi5cbiAqL1xuXG5pbXBvcnQgeyBpbnZhbGlkRGVmYXVsdEJ1Y2tldCwgaW52YWxpZFVybCB9IGZyb20gJy4vZXJyb3InO1xuaW1wb3J0IHsgREVGQVVMVF9IT1NUIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuXG4vKipcbiAqIEZpcmViYXNlIFN0b3JhZ2UgbG9jYXRpb24gZGF0YS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIExvY2F0aW9uIHtcbiAgcHJpdmF0ZSBwYXRoXzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBidWNrZXQ6IHN0cmluZywgcGF0aDogc3RyaW5nKSB7XG4gICAgdGhpcy5wYXRoXyA9IHBhdGg7XG4gIH1cblxuICBnZXQgcGF0aCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnBhdGhfO1xuICB9XG5cbiAgZ2V0IGlzUm9vdCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wYXRoLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIGZ1bGxTZXJ2ZXJVcmwoKTogc3RyaW5nIHtcbiAgICBjb25zdCBlbmNvZGUgPSBlbmNvZGVVUklDb21wb25lbnQ7XG4gICAgcmV0dXJuICcvYi8nICsgZW5jb2RlKHRoaXMuYnVja2V0KSArICcvby8nICsgZW5jb2RlKHRoaXMucGF0aCk7XG4gIH1cblxuICBidWNrZXRPbmx5U2VydmVyVXJsKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZW5jb2RlID0gZW5jb2RlVVJJQ29tcG9uZW50O1xuICAgIHJldHVybiAnL2IvJyArIGVuY29kZSh0aGlzLmJ1Y2tldCkgKyAnL28nO1xuICB9XG5cbiAgc3RhdGljIG1ha2VGcm9tQnVja2V0U3BlYyhidWNrZXRTdHJpbmc6IHN0cmluZywgaG9zdDogc3RyaW5nKTogTG9jYXRpb24ge1xuICAgIGxldCBidWNrZXRMb2NhdGlvbjtcbiAgICB0cnkge1xuICAgICAgYnVja2V0TG9jYXRpb24gPSBMb2NhdGlvbi5tYWtlRnJvbVVybChidWNrZXRTdHJpbmcsIGhvc3QpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIE5vdCB2YWxpZCBVUkwsIHVzZSBhcy1pcy4gVGhpcyBsZXRzIHlvdSBwdXQgYmFyZSBidWNrZXQgbmFtZXMgaW5cbiAgICAgIC8vIGNvbmZpZy5cbiAgICAgIHJldHVybiBuZXcgTG9jYXRpb24oYnVja2V0U3RyaW5nLCAnJyk7XG4gICAgfVxuICAgIGlmIChidWNrZXRMb2NhdGlvbi5wYXRoID09PSAnJykge1xuICAgICAgcmV0dXJuIGJ1Y2tldExvY2F0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBpbnZhbGlkRGVmYXVsdEJ1Y2tldChidWNrZXRTdHJpbmcpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBtYWtlRnJvbVVybCh1cmw6IHN0cmluZywgaG9zdDogc3RyaW5nKTogTG9jYXRpb24ge1xuICAgIGxldCBsb2NhdGlvbjogTG9jYXRpb24gfCBudWxsID0gbnVsbDtcbiAgICBjb25zdCBidWNrZXREb21haW4gPSAnKFtBLVphLXowLTkuXFxcXC1fXSspJztcblxuICAgIGZ1bmN0aW9uIGdzTW9kaWZ5KGxvYzogTG9jYXRpb24pOiB2b2lkIHtcbiAgICAgIGlmIChsb2MucGF0aC5jaGFyQXQobG9jLnBhdGgubGVuZ3RoIC0gMSkgPT09ICcvJykge1xuICAgICAgICBsb2MucGF0aF8gPSBsb2MucGF0aF8uc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBnc1BhdGggPSAnKC8oLiopKT8kJztcbiAgICBjb25zdCBnc1JlZ2V4ID0gbmV3IFJlZ0V4cCgnXmdzOi8vJyArIGJ1Y2tldERvbWFpbiArIGdzUGF0aCwgJ2knKTtcbiAgICBjb25zdCBnc0luZGljZXMgPSB7IGJ1Y2tldDogMSwgcGF0aDogMyB9O1xuXG4gICAgZnVuY3Rpb24gaHR0cE1vZGlmeShsb2M6IExvY2F0aW9uKTogdm9pZCB7XG4gICAgICBsb2MucGF0aF8gPSBkZWNvZGVVUklDb21wb25lbnQobG9jLnBhdGgpO1xuICAgIH1cbiAgICBjb25zdCB2ZXJzaW9uID0gJ3ZbQS1aYS16MC05X10rJztcbiAgICBjb25zdCBmaXJlYmFzZVN0b3JhZ2VIb3N0ID0gaG9zdC5yZXBsYWNlKC9bLl0vZywgJ1xcXFwuJyk7XG4gICAgY29uc3QgZmlyZWJhc2VTdG9yYWdlUGF0aCA9ICcoLyhbXj8jXSopLiopPyQnO1xuICAgIGNvbnN0IGZpcmViYXNlU3RvcmFnZVJlZ0V4cCA9IG5ldyBSZWdFeHAoXG4gICAgICBgXmh0dHBzPzovLyR7ZmlyZWJhc2VTdG9yYWdlSG9zdH0vJHt2ZXJzaW9ufS9iLyR7YnVja2V0RG9tYWlufS9vJHtmaXJlYmFzZVN0b3JhZ2VQYXRofWAsXG4gICAgICAnaSdcbiAgICApO1xuICAgIGNvbnN0IGZpcmViYXNlU3RvcmFnZUluZGljZXMgPSB7IGJ1Y2tldDogMSwgcGF0aDogMyB9O1xuXG4gICAgY29uc3QgY2xvdWRTdG9yYWdlSG9zdCA9XG4gICAgICBob3N0ID09PSBERUZBVUxUX0hPU1RcbiAgICAgICAgPyAnKD86c3RvcmFnZS5nb29nbGVhcGlzLmNvbXxzdG9yYWdlLmNsb3VkLmdvb2dsZS5jb20pJ1xuICAgICAgICA6IGhvc3Q7XG4gICAgY29uc3QgY2xvdWRTdG9yYWdlUGF0aCA9ICcoW14/I10qKSc7XG4gICAgY29uc3QgY2xvdWRTdG9yYWdlUmVnRXhwID0gbmV3IFJlZ0V4cChcbiAgICAgIGBeaHR0cHM/Oi8vJHtjbG91ZFN0b3JhZ2VIb3N0fS8ke2J1Y2tldERvbWFpbn0vJHtjbG91ZFN0b3JhZ2VQYXRofWAsXG4gICAgICAnaSdcbiAgICApO1xuICAgIGNvbnN0IGNsb3VkU3RvcmFnZUluZGljZXMgPSB7IGJ1Y2tldDogMSwgcGF0aDogMiB9O1xuXG4gICAgY29uc3QgZ3JvdXBzID0gW1xuICAgICAgeyByZWdleDogZ3NSZWdleCwgaW5kaWNlczogZ3NJbmRpY2VzLCBwb3N0TW9kaWZ5OiBnc01vZGlmeSB9LFxuICAgICAge1xuICAgICAgICByZWdleDogZmlyZWJhc2VTdG9yYWdlUmVnRXhwLFxuICAgICAgICBpbmRpY2VzOiBmaXJlYmFzZVN0b3JhZ2VJbmRpY2VzLFxuICAgICAgICBwb3N0TW9kaWZ5OiBodHRwTW9kaWZ5XG4gICAgICB9LFxuICAgICAge1xuICAgICAgICByZWdleDogY2xvdWRTdG9yYWdlUmVnRXhwLFxuICAgICAgICBpbmRpY2VzOiBjbG91ZFN0b3JhZ2VJbmRpY2VzLFxuICAgICAgICBwb3N0TW9kaWZ5OiBodHRwTW9kaWZ5XG4gICAgICB9XG4gICAgXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZ3JvdXAgPSBncm91cHNbaV07XG4gICAgICBjb25zdCBjYXB0dXJlcyA9IGdyb3VwLnJlZ2V4LmV4ZWModXJsKTtcbiAgICAgIGlmIChjYXB0dXJlcykge1xuICAgICAgICBjb25zdCBidWNrZXRWYWx1ZSA9IGNhcHR1cmVzW2dyb3VwLmluZGljZXMuYnVja2V0XTtcbiAgICAgICAgbGV0IHBhdGhWYWx1ZSA9IGNhcHR1cmVzW2dyb3VwLmluZGljZXMucGF0aF07XG4gICAgICAgIGlmICghcGF0aFZhbHVlKSB7XG4gICAgICAgICAgcGF0aFZhbHVlID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgbG9jYXRpb24gPSBuZXcgTG9jYXRpb24oYnVja2V0VmFsdWUsIHBhdGhWYWx1ZSk7XG4gICAgICAgIGdyb3VwLnBvc3RNb2RpZnkobG9jYXRpb24pO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGxvY2F0aW9uID09IG51bGwpIHtcbiAgICAgIHRocm93IGludmFsaWRVcmwodXJsKTtcbiAgICB9XG4gICAgcmV0dXJuIGxvY2F0aW9uO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IFN0b3JhZ2VFcnJvciB9IGZyb20gJy4vZXJyb3InO1xuaW1wb3J0IHsgUmVxdWVzdCB9IGZyb20gJy4vcmVxdWVzdCc7XG5cbi8qKlxuICogQSByZXF1ZXN0IHdob3NlIHByb21pc2UgYWx3YXlzIGZhaWxzLlxuICovXG5leHBvcnQgY2xhc3MgRmFpbFJlcXVlc3Q8VD4gaW1wbGVtZW50cyBSZXF1ZXN0PFQ+IHtcbiAgcHJvbWlzZV86IFByb21pc2U8VD47XG5cbiAgY29uc3RydWN0b3IoZXJyb3I6IFN0b3JhZ2VFcnJvcikge1xuICAgIHRoaXMucHJvbWlzZV8gPSBQcm9taXNlLnJlamVjdDxUPihlcnJvcik7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgZ2V0UHJvbWlzZSgpOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5wcm9taXNlXztcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBjYW5jZWwoX2FwcERlbGV0ZSA9IGZhbHNlKTogdm9pZCB7fVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQGZpbGVvdmVydmlldyBQcm92aWRlcyBhIG1ldGhvZCBmb3IgcnVubmluZyBhIGZ1bmN0aW9uIHdpdGggZXhwb25lbnRpYWxcbiAqIGJhY2tvZmYuXG4gKi9cbnR5cGUgaWQgPSAocDE6IGJvb2xlYW4pID0+IHZvaWQ7XG5cbmV4cG9ydCB7IGlkIH07XG5cbi8qKlxuICogQWNjZXB0cyBhIGNhbGxiYWNrIGZvciBhbiBhY3Rpb24gdG8gcGVyZm9ybSAoYGRvUmVxdWVzdGApLFxuICogYW5kIHRoZW4gYSBjYWxsYmFjayBmb3Igd2hlbiB0aGUgYmFja29mZiBoYXMgY29tcGxldGVkIChgYmFja29mZkNvbXBsZXRlQ2JgKS5cbiAqIFRoZSBjYWxsYmFjayBzZW50IHRvIHN0YXJ0IHJlcXVpcmVzIGFuIGFyZ3VtZW50IHRvIGNhbGwgKGBvblJlcXVlc3RDb21wbGV0ZWApLlxuICogV2hlbiBgc3RhcnRgIGNhbGxzIGBkb1JlcXVlc3RgLCBpdCBwYXNzZXMgYSBjYWxsYmFjayBmb3Igd2hlbiB0aGUgcmVxdWVzdCBoYXNcbiAqIGNvbXBsZXRlZCwgYG9uUmVxdWVzdENvbXBsZXRlYC4gQmFzZWQgb24gdGhpcywgdGhlIGJhY2tvZmYgY29udGludWVzLCB3aXRoXG4gKiBhbm90aGVyIGNhbGwgdG8gYGRvUmVxdWVzdGAgYW5kIHRoZSBhYm92ZSBsb29wIGNvbnRpbnVlcyB1bnRpbCB0aGUgdGltZW91dFxuICogaXMgaGl0LCBvciBhIHN1Y2Nlc3NmdWwgcmVzcG9uc2Ugb2NjdXJzLlxuICogQGRlc2NyaXB0aW9uXG4gKiBAcGFyYW0gZG9SZXF1ZXN0IENhbGxiYWNrIHRvIHBlcmZvcm0gcmVxdWVzdFxuICogQHBhcmFtIGJhY2tvZmZDb21wbGV0ZUNiIENhbGxiYWNrIHRvIGNhbGwgd2hlbiBiYWNrb2ZmIGhhcyBiZWVuIGNvbXBsZXRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RhcnQoXG4gIGRvUmVxdWVzdDogKFxuICAgIG9uUmVxdWVzdENvbXBsZXRlOiAoc3VjY2VzczogYm9vbGVhbikgPT4gdm9pZCxcbiAgICBjYW5jZWxlZDogYm9vbGVhblxuICApID0+IHZvaWQsXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIGJhY2tvZmZDb21wbGV0ZUNiOiAoLi4uYXJnczogYW55W10pID0+IHVua25vd24sXG4gIHRpbWVvdXQ6IG51bWJlclxuKTogaWQge1xuICAvLyBUT0RPKGFuZHlzb3RvKTogbWFrZSB0aGlzIGNvZGUgY2xlYW5lciAocHJvYmFibHkgcmVmYWN0b3IgaW50byBhbiBhY3R1YWxcbiAgLy8gdHlwZSBpbnN0ZWFkIG9mIGEgYnVuY2ggb2YgZnVuY3Rpb25zIHdpdGggc3RhdGUgc2hhcmVkIGluIHRoZSBjbG9zdXJlKVxuICBsZXQgd2FpdFNlY29uZHMgPSAxO1xuICAvLyBXb3VsZCB0eXBlIHRoaXMgYXMgXCJudW1iZXJcIiBidXQgdGhhdCBkb2Vzbid0IHdvcmsgZm9yIE5vZGUgc28gwq9cXF8o44OEKV8vwq9cbiAgLy8gVE9ETzogZmluZCBhIHdheSB0byBleGNsdWRlIE5vZGUgdHlwZSBkZWZpbml0aW9uIGZvciBzdG9yYWdlIGJlY2F1c2Ugc3RvcmFnZSBvbmx5IHdvcmtzIGluIGJyb3dzZXJcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgbGV0IHJldHJ5VGltZW91dElkOiBhbnkgPSBudWxsO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBsZXQgZ2xvYmFsVGltZW91dElkOiBhbnkgPSBudWxsO1xuICBsZXQgaGl0VGltZW91dCA9IGZhbHNlO1xuICBsZXQgY2FuY2VsU3RhdGUgPSAwO1xuXG4gIGZ1bmN0aW9uIGNhbmNlbGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjYW5jZWxTdGF0ZSA9PT0gMjtcbiAgfVxuICBsZXQgdHJpZ2dlcmVkQ2FsbGJhY2sgPSBmYWxzZTtcblxuICBmdW5jdGlvbiB0cmlnZ2VyQ2FsbGJhY2soLi4uYXJnczogYW55W10pOiB2b2lkIHtcbiAgICBpZiAoIXRyaWdnZXJlZENhbGxiYWNrKSB7XG4gICAgICB0cmlnZ2VyZWRDYWxsYmFjayA9IHRydWU7XG4gICAgICBiYWNrb2ZmQ29tcGxldGVDYi5hcHBseShudWxsLCBhcmdzKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjYWxsV2l0aERlbGF5KG1pbGxpczogbnVtYmVyKTogdm9pZCB7XG4gICAgcmV0cnlUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHJldHJ5VGltZW91dElkID0gbnVsbDtcbiAgICAgIGRvUmVxdWVzdChyZXNwb25zZUhhbmRsZXIsIGNhbmNlbGVkKCkpO1xuICAgIH0sIG1pbGxpcyk7XG4gIH1cblxuICBmdW5jdGlvbiBjbGVhckdsb2JhbFRpbWVvdXQoKTogdm9pZCB7XG4gICAgaWYgKGdsb2JhbFRpbWVvdXRJZCkge1xuICAgICAgY2xlYXJUaW1lb3V0KGdsb2JhbFRpbWVvdXRJZCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmVzcG9uc2VIYW5kbGVyKHN1Y2Nlc3M6IGJvb2xlYW4sIC4uLmFyZ3M6IGFueVtdKTogdm9pZCB7XG4gICAgaWYgKHRyaWdnZXJlZENhbGxiYWNrKSB7XG4gICAgICBjbGVhckdsb2JhbFRpbWVvdXQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHN1Y2Nlc3MpIHtcbiAgICAgIGNsZWFyR2xvYmFsVGltZW91dCgpO1xuICAgICAgdHJpZ2dlckNhbGxiYWNrLmNhbGwobnVsbCwgc3VjY2VzcywgLi4uYXJncyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG11c3RTdG9wID0gY2FuY2VsZWQoKSB8fCBoaXRUaW1lb3V0O1xuICAgIGlmIChtdXN0U3RvcCkge1xuICAgICAgY2xlYXJHbG9iYWxUaW1lb3V0KCk7XG4gICAgICB0cmlnZ2VyQ2FsbGJhY2suY2FsbChudWxsLCBzdWNjZXNzLCAuLi5hcmdzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHdhaXRTZWNvbmRzIDwgNjQpIHtcbiAgICAgIC8qIFRPRE8oYW5keXNvdG8pOiBkb24ndCBiYWNrIG9mZiBzbyBxdWlja2x5IGlmIHdlIGtub3cgd2UncmUgb2ZmbGluZS4gKi9cbiAgICAgIHdhaXRTZWNvbmRzICo9IDI7XG4gICAgfVxuICAgIGxldCB3YWl0TWlsbGlzO1xuICAgIGlmIChjYW5jZWxTdGF0ZSA9PT0gMSkge1xuICAgICAgY2FuY2VsU3RhdGUgPSAyO1xuICAgICAgd2FpdE1pbGxpcyA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdhaXRNaWxsaXMgPSAod2FpdFNlY29uZHMgKyBNYXRoLnJhbmRvbSgpKSAqIDEwMDA7XG4gICAgfVxuICAgIGNhbGxXaXRoRGVsYXkod2FpdE1pbGxpcyk7XG4gIH1cbiAgbGV0IHN0b3BwZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBzdG9wKHdhc1RpbWVvdXQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoc3RvcHBlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzdG9wcGVkID0gdHJ1ZTtcbiAgICBjbGVhckdsb2JhbFRpbWVvdXQoKTtcbiAgICBpZiAodHJpZ2dlcmVkQ2FsbGJhY2spIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHJldHJ5VGltZW91dElkICE9PSBudWxsKSB7XG4gICAgICBpZiAoIXdhc1RpbWVvdXQpIHtcbiAgICAgICAgY2FuY2VsU3RhdGUgPSAyO1xuICAgICAgfVxuICAgICAgY2xlYXJUaW1lb3V0KHJldHJ5VGltZW91dElkKTtcbiAgICAgIGNhbGxXaXRoRGVsYXkoMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghd2FzVGltZW91dCkge1xuICAgICAgICBjYW5jZWxTdGF0ZSA9IDE7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGNhbGxXaXRoRGVsYXkoMCk7XG4gIGdsb2JhbFRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgIGhpdFRpbWVvdXQgPSB0cnVlO1xuICAgIHN0b3AodHJ1ZSk7XG4gIH0sIHRpbWVvdXQpO1xuICByZXR1cm4gc3RvcDtcbn1cblxuLyoqXG4gKiBTdG9wcyB0aGUgcmV0cnkgbG9vcCBmcm9tIHJlcGVhdGluZy5cbiAqIElmIHRoZSBmdW5jdGlvbiBpcyBjdXJyZW50bHkgXCJpbiBiZXR3ZWVuXCIgcmV0cmllcywgaXQgaXMgaW52b2tlZCBpbW1lZGlhdGVseVxuICogd2l0aCB0aGUgc2Vjb25kIHBhcmFtZXRlciBhcyBcInRydWVcIi4gT3RoZXJ3aXNlLCBpdCB3aWxsIGJlIGludm9rZWQgb25jZSBtb3JlXG4gKiBhZnRlciB0aGUgY3VycmVudCBpbnZvY2F0aW9uIGZpbmlzaGVzIGlmZiB0aGUgY3VycmVudCBpbnZvY2F0aW9uIHdvdWxkIGhhdmVcbiAqIHRyaWdnZXJlZCBhbm90aGVyIHJldHJ5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RvcChpZDogaWQpOiB2b2lkIHtcbiAgaWQoZmFsc2UpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGludmFsaWRBcmd1bWVudCB9IGZyb20gJy4vZXJyb3InO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNKdXN0RGVmPFQ+KHA6IFQgfCBudWxsIHwgdW5kZWZpbmVkKTogcCBpcyBUIHwgbnVsbCB7XG4gIHJldHVybiBwICE9PSB2b2lkIDA7XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXR5cGVzXG5leHBvcnQgZnVuY3Rpb24gaXNGdW5jdGlvbihwOiB1bmtub3duKTogcCBpcyBGdW5jdGlvbiB7XG4gIHJldHVybiB0eXBlb2YgcCA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTm9uQXJyYXlPYmplY3QocDogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIHAgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KHApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdHJpbmcocDogdW5rbm93bik6IHAgaXMgc3RyaW5nIHtcbiAgcmV0dXJuIHR5cGVvZiBwID09PSAnc3RyaW5nJyB8fCBwIGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNOYXRpdmVCbG9iKHA6IHVua25vd24pOiBwIGlzIEJsb2Ige1xuICByZXR1cm4gaXNOYXRpdmVCbG9iRGVmaW5lZCgpICYmIHAgaW5zdGFuY2VvZiBCbG9iO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNOYXRpdmVCbG9iRGVmaW5lZCgpOiBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGVvZiBCbG9iICE9PSAndW5kZWZpbmVkJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTnVtYmVyKFxuICBhcmd1bWVudDogc3RyaW5nLFxuICBtaW5WYWx1ZTogbnVtYmVyLFxuICBtYXhWYWx1ZTogbnVtYmVyLFxuICB2YWx1ZTogbnVtYmVyXG4pOiB2b2lkIHtcbiAgaWYgKHZhbHVlIDwgbWluVmFsdWUpIHtcbiAgICB0aHJvdyBpbnZhbGlkQXJndW1lbnQoXG4gICAgICBgSW52YWxpZCB2YWx1ZSBmb3IgJyR7YXJndW1lbnR9Jy4gRXhwZWN0ZWQgJHttaW5WYWx1ZX0gb3IgZ3JlYXRlci5gXG4gICAgKTtcbiAgfVxuICBpZiAodmFsdWUgPiBtYXhWYWx1ZSkge1xuICAgIHRocm93IGludmFsaWRBcmd1bWVudChcbiAgICAgIGBJbnZhbGlkIHZhbHVlIGZvciAnJHthcmd1bWVudH0nLiBFeHBlY3RlZCAke21heFZhbHVlfSBvciBsZXNzLmBcbiAgICApO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IEZ1bmN0aW9ucyB0byBjcmVhdGUgYW5kIG1hbmlwdWxhdGUgVVJMcyBmb3IgdGhlIHNlcnZlciBBUEkuXG4gKi9cbmltcG9ydCB7IFVybFBhcmFtcyB9IGZyb20gJy4vcmVxdWVzdGluZm8nO1xuXG5leHBvcnQgZnVuY3Rpb24gbWFrZVVybChcbiAgdXJsUGFydDogc3RyaW5nLFxuICBob3N0OiBzdHJpbmcsXG4gIHByb3RvY29sOiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGxldCBvcmlnaW4gPSBob3N0O1xuICBpZiAocHJvdG9jb2wgPT0gbnVsbCkge1xuICAgIG9yaWdpbiA9IGBodHRwczovLyR7aG9zdH1gO1xuICB9XG4gIHJldHVybiBgJHtwcm90b2NvbH06Ly8ke29yaWdpbn0vdjAke3VybFBhcnR9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VRdWVyeVN0cmluZyhwYXJhbXM6IFVybFBhcmFtcyk6IHN0cmluZyB7XG4gIGNvbnN0IGVuY29kZSA9IGVuY29kZVVSSUNvbXBvbmVudDtcbiAgbGV0IHF1ZXJ5UGFydCA9ICc/JztcbiAgZm9yIChjb25zdCBrZXkgaW4gcGFyYW1zKSB7XG4gICAgaWYgKHBhcmFtcy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICBjb25zdCBuZXh0UGFydCA9IGVuY29kZShrZXkpICsgJz0nICsgZW5jb2RlKHBhcmFtc1trZXldKTtcbiAgICAgIHF1ZXJ5UGFydCA9IHF1ZXJ5UGFydCArIG5leHRQYXJ0ICsgJyYnO1xuICAgIH1cbiAgfVxuXG4gIC8vIENob3Agb2ZmIHRoZSBleHRyYSAnJicgb3IgJz8nIG9uIHRoZSBlbmRcbiAgcXVlcnlQYXJ0ID0gcXVlcnlQYXJ0LnNsaWNlKDAsIC0xKTtcbiAgcmV0dXJuIHF1ZXJ5UGFydDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuLyoqIE5ldHdvcmsgaGVhZGVycyAqL1xuZXhwb3J0IHR5cGUgSGVhZGVycyA9IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbi8qKiBSZXNwb25zZSB0eXBlIGV4cG9zZWQgYnkgdGhlIG5ldHdvcmtpbmcgQVBJcy4gKi9cbmV4cG9ydCB0eXBlIENvbm5lY3Rpb25UeXBlID1cbiAgfCBzdHJpbmdcbiAgfCBBcnJheUJ1ZmZlclxuICB8IEJsb2JcbiAgfCBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PjtcblxuLyoqXG4gKiBBIGxpZ2h0d2VpZ2h0IHdyYXBwZXIgYXJvdW5kIFhNTEh0dHBSZXF1ZXN0IHdpdGggYVxuICogZ29vZy5uZXQuWGhySW8tbGlrZSBpbnRlcmZhY2UuXG4gKlxuICogWW91IGNhbiBjcmVhdGUgYSBuZXcgY29ubmVjdGlvbiBieSBpbnZva2luZyBgbmV3VGV4dENvbm5lY3Rpb24oKWAsXG4gKiBgbmV3Qnl0ZXNDb25uZWN0aW9uKClgIG9yIGBuZXdTdHJlYW1Db25uZWN0aW9uKClgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbm5lY3Rpb248VCBleHRlbmRzIENvbm5lY3Rpb25UeXBlPiB7XG4gIC8qKlxuICAgKiBTZW5kcyBhIHJlcXVlc3QgdG8gdGhlIHByb3ZpZGVkIFVSTC5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgbmV2ZXIgcmVqZWN0cyBpdHMgcHJvbWlzZS4gSW4gY2FzZSBvZiBlbmNvdW50ZXJpbmcgYW4gZXJyb3IsXG4gICAqIGl0IHNldHMgYW4gZXJyb3IgY29kZSBpbnRlcm5hbGx5IHdoaWNoIGNhbiBiZSBhY2Nlc3NlZCBieSBjYWxsaW5nXG4gICAqIGdldEVycm9yQ29kZSgpIGJ5IGNhbGxlcnMuXG4gICAqL1xuICBzZW5kKFxuICAgIHVybDogc3RyaW5nLFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIGlzVXNpbmdFbXVsYXRvcjogYm9vbGVhbixcbiAgICBib2R5PzogQXJyYXlCdWZmZXJWaWV3IHwgQmxvYiB8IHN0cmluZyB8IG51bGwsXG4gICAgaGVhZGVycz86IEhlYWRlcnNcbiAgKTogUHJvbWlzZTx2b2lkPjtcblxuICBnZXRFcnJvckNvZGUoKTogRXJyb3JDb2RlO1xuXG4gIGdldFN0YXR1cygpOiBudW1iZXI7XG5cbiAgZ2V0UmVzcG9uc2UoKTogVDtcblxuICBnZXRFcnJvclRleHQoKTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBYm9ydCB0aGUgcmVxdWVzdC5cbiAgICovXG4gIGFib3J0KCk6IHZvaWQ7XG5cbiAgZ2V0UmVzcG9uc2VIZWFkZXIoaGVhZGVyOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsO1xuXG4gIGFkZFVwbG9hZFByb2dyZXNzTGlzdGVuZXIobGlzdGVuZXI6IChwMTogUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCk6IHZvaWQ7XG5cbiAgcmVtb3ZlVXBsb2FkUHJvZ3Jlc3NMaXN0ZW5lcihsaXN0ZW5lcjogKHAxOiBQcm9ncmVzc0V2ZW50KSA9PiB2b2lkKTogdm9pZDtcbn1cblxuLyoqXG4gKiBFcnJvciBjb2RlcyBmb3IgcmVxdWVzdHMgbWFkZSBieSB0aGUgWGhySW8gd3JhcHBlci5cbiAqL1xuZXhwb3J0IGVudW0gRXJyb3JDb2RlIHtcbiAgTk9fRVJST1IgPSAwLFxuICBORVRXT1JLX0VSUk9SID0gMSxcbiAgQUJPUlQgPSAyXG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBDaGVja3MgdGhlIHN0YXR1cyBjb2RlIHRvIHNlZSBpZiB0aGUgYWN0aW9uIHNob3VsZCBiZSByZXRyaWVkLlxuICpcbiAqIEBwYXJhbSBzdGF0dXMgQ3VycmVudCBIVFRQIHN0YXR1cyBjb2RlIHJldHVybmVkIGJ5IHNlcnZlci5cbiAqIEBwYXJhbSBhZGRpdGlvbmFsUmV0cnlDb2RlcyBhZGRpdGlvbmFsIHJldHJ5IGNvZGVzIHRvIGNoZWNrIGFnYWluc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUmV0cnlTdGF0dXNDb2RlKFxuICBzdGF0dXM6IG51bWJlcixcbiAgYWRkaXRpb25hbFJldHJ5Q29kZXM6IG51bWJlcltdXG4pOiBib29sZWFuIHtcbiAgLy8gVGhlIGNvZGVzIGZvciB3aGljaCB0byByZXRyeSBjYW1lIGZyb20gdGhpcyBwYWdlOlxuICAvLyBodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vc3RvcmFnZS9kb2NzL2V4cG9uZW50aWFsLWJhY2tvZmZcbiAgY29uc3QgaXNGaXZlSHVuZHJlZENvZGUgPSBzdGF0dXMgPj0gNTAwICYmIHN0YXR1cyA8IDYwMDtcbiAgY29uc3QgZXh0cmFSZXRyeUNvZGVzID0gW1xuICAgIC8vIFJlcXVlc3QgVGltZW91dDogd2ViIHNlcnZlciBkaWRuJ3QgcmVjZWl2ZSBmdWxsIHJlcXVlc3QgaW4gdGltZS5cbiAgICA0MDgsXG4gICAgLy8gVG9vIE1hbnkgUmVxdWVzdHM6IHlvdSdyZSBnZXR0aW5nIHJhdGUtbGltaXRlZCwgYmFzaWNhbGx5LlxuICAgIDQyOVxuICBdO1xuICBjb25zdCBpc0V4dHJhUmV0cnlDb2RlID0gZXh0cmFSZXRyeUNvZGVzLmluZGV4T2Yoc3RhdHVzKSAhPT0gLTE7XG4gIGNvbnN0IGlzQWRkaXRpb25hbFJldHJ5Q29kZSA9IGFkZGl0aW9uYWxSZXRyeUNvZGVzLmluZGV4T2Yoc3RhdHVzKSAhPT0gLTE7XG4gIHJldHVybiBpc0ZpdmVIdW5kcmVkQ29kZSB8fCBpc0V4dHJhUmV0cnlDb2RlIHx8IGlzQWRkaXRpb25hbFJldHJ5Q29kZTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgRGVmaW5lcyBtZXRob2RzIHVzZWQgdG8gYWN0dWFsbHkgc2VuZCBIVFRQIHJlcXVlc3RzIGZyb21cbiAqIGFic3RyYWN0IHJlcHJlc2VudGF0aW9ucy5cbiAqL1xuXG5pbXBvcnQgeyBpZCBhcyBiYWNrb2ZmSWQsIHN0YXJ0LCBzdG9wIH0gZnJvbSAnLi9iYWNrb2ZmJztcbmltcG9ydCB7IGFwcERlbGV0ZWQsIGNhbmNlbGVkLCByZXRyeUxpbWl0RXhjZWVkZWQsIHVua25vd24gfSBmcm9tICcuL2Vycm9yJztcbmltcG9ydCB7IEVycm9ySGFuZGxlciwgUmVxdWVzdEhhbmRsZXIsIFJlcXVlc3RJbmZvIH0gZnJvbSAnLi9yZXF1ZXN0aW5mbyc7XG5pbXBvcnQgeyBpc0p1c3REZWYgfSBmcm9tICcuL3R5cGUnO1xuaW1wb3J0IHsgbWFrZVF1ZXJ5U3RyaW5nIH0gZnJvbSAnLi91cmwnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbiwgRXJyb3JDb2RlLCBIZWFkZXJzLCBDb25uZWN0aW9uVHlwZSB9IGZyb20gJy4vY29ubmVjdGlvbic7XG5pbXBvcnQgeyBpc1JldHJ5U3RhdHVzQ29kZSB9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlcXVlc3Q8VD4ge1xuICBnZXRQcm9taXNlKCk6IFByb21pc2U8VD47XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgdGhlIHJlcXVlc3QuIElNUE9SVEFOVDogdGhlIHByb21pc2UgbWF5IHN0aWxsIGJlIHJlc29sdmVkIHdpdGggYW5cbiAgICogYXBwcm9wcmlhdGUgdmFsdWUgKGlmIHRoZSByZXF1ZXN0IGlzIGZpbmlzaGVkIGJlZm9yZSB5b3UgY2FsbCB0aGlzIG1ldGhvZCxcbiAgICogYnV0IHRoZSBwcm9taXNlIGhhcyBub3QgeWV0IGJlZW4gcmVzb2x2ZWQpLCBzbyBkb24ndCBqdXN0IGFzc3VtZSBpdCB3aWxsIGJlXG4gICAqIHJlamVjdGVkIGlmIHlvdSBjYWxsIHRoaXMgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSBhcHBEZWxldGUgLSBUcnVlIGlmIHRoZSBjYW5jZWxhdGlvbiBjYW1lIGZyb20gdGhlIGFwcCBiZWluZyBkZWxldGVkLlxuICAgKi9cbiAgY2FuY2VsKGFwcERlbGV0ZT86IGJvb2xlYW4pOiB2b2lkO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgbmV0d29yayBsb2dpYyBmb3IgYWxsIFN0b3JhZ2UgUmVxdWVzdHMsIGluY2x1ZGluZyBlcnJvciByZXBvcnRpbmcgYW5kXG4gKiByZXRyaWVzIHdpdGggYmFja29mZi5cbiAqXG4gKiBAcGFyYW0gSSAtIHRoZSB0eXBlIG9mIHRoZSBiYWNrZW5kJ3MgbmV0d29yayByZXNwb25zZS5cbiAqIEBwYXJhbSAtIE8gdGhlIG91dHB1dCB0eXBlIHVzZWQgYnkgdGhlIHJlc3Qgb2YgdGhlIFNESy4gVGhlIGNvbnZlcnNpb25cbiAqIGhhcHBlbnMgaW4gdGhlIHNwZWNpZmllZCBgY2FsbGJhY2tfYC5cbiAqL1xuY2xhc3MgTmV0d29ya1JlcXVlc3Q8SSBleHRlbmRzIENvbm5lY3Rpb25UeXBlLCBPPiBpbXBsZW1lbnRzIFJlcXVlc3Q8Tz4ge1xuICBwcml2YXRlIHBlbmRpbmdDb25uZWN0aW9uXzogQ29ubmVjdGlvbjxJPiB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJhY2tvZmZJZF86IGJhY2tvZmZJZCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHJlc29sdmVfITogKHZhbHVlPzogTyB8IFByb21pc2VMaWtlPE8+KSA9PiB2b2lkO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBwcml2YXRlIHJlamVjdF8hOiAocmVhc29uPzogYW55KSA9PiB2b2lkO1xuICBwcml2YXRlIGNhbmNlbGVkXzogYm9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIGFwcERlbGV0ZV86IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBwcm9taXNlXzogUHJvbWlzZTxPPjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHVybF86IHN0cmluZyxcbiAgICBwcml2YXRlIG1ldGhvZF86IHN0cmluZyxcbiAgICBwcml2YXRlIGhlYWRlcnNfOiBIZWFkZXJzLFxuICAgIHByaXZhdGUgYm9keV86IHN0cmluZyB8IEJsb2IgfCBVaW50OEFycmF5IHwgbnVsbCxcbiAgICBwcml2YXRlIHN1Y2Nlc3NDb2Rlc186IG51bWJlcltdLFxuICAgIHByaXZhdGUgYWRkaXRpb25hbFJldHJ5Q29kZXNfOiBudW1iZXJbXSxcbiAgICBwcml2YXRlIGNhbGxiYWNrXzogUmVxdWVzdEhhbmRsZXI8SSwgTz4sXG4gICAgcHJpdmF0ZSBlcnJvckNhbGxiYWNrXzogRXJyb3JIYW5kbGVyIHwgbnVsbCxcbiAgICBwcml2YXRlIHRpbWVvdXRfOiBudW1iZXIsXG4gICAgcHJpdmF0ZSBwcm9ncmVzc0NhbGxiYWNrXzogKChwMTogbnVtYmVyLCBwMjogbnVtYmVyKSA9PiB2b2lkKSB8IG51bGwsXG4gICAgcHJpdmF0ZSBjb25uZWN0aW9uRmFjdG9yeV86ICgpID0+IENvbm5lY3Rpb248ST4sXG4gICAgcHJpdmF0ZSByZXRyeSA9IHRydWUsXG4gICAgcHJpdmF0ZSBpc1VzaW5nRW11bGF0b3IgPSBmYWxzZVxuICApIHtcbiAgICB0aGlzLnByb21pc2VfID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5yZXNvbHZlXyA9IHJlc29sdmUgYXMgKHZhbHVlPzogTyB8IFByb21pc2VMaWtlPE8+KSA9PiB2b2lkO1xuICAgICAgdGhpcy5yZWplY3RfID0gcmVqZWN0O1xuICAgICAgdGhpcy5zdGFydF8oKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBY3R1YWxseSBzdGFydHMgdGhlIHJldHJ5IGxvb3AuXG4gICAqL1xuICBwcml2YXRlIHN0YXJ0XygpOiB2b2lkIHtcbiAgICBjb25zdCBkb1RoZVJlcXVlc3Q6IChcbiAgICAgIGJhY2tvZmZDYWxsYmFjazogKHN1Y2Nlc3M6IGJvb2xlYW4sIC4uLnAyOiB1bmtub3duW10pID0+IHZvaWQsXG4gICAgICBjYW5jZWxlZDogYm9vbGVhblxuICAgICkgPT4gdm9pZCA9IChiYWNrb2ZmQ2FsbGJhY2ssIGNhbmNlbGVkKSA9PiB7XG4gICAgICBpZiAoY2FuY2VsZWQpIHtcbiAgICAgICAgYmFja29mZkNhbGxiYWNrKGZhbHNlLCBuZXcgUmVxdWVzdEVuZFN0YXR1cyhmYWxzZSwgbnVsbCwgdHJ1ZSkpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5jb25uZWN0aW9uRmFjdG9yeV8oKTtcbiAgICAgIHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25fID0gY29ubmVjdGlvbjtcblxuICAgICAgY29uc3QgcHJvZ3Jlc3NMaXN0ZW5lcjogKFxuICAgICAgICBwcm9ncmVzc0V2ZW50OiBQcm9ncmVzc0V2ZW50XG4gICAgICApID0+IHZvaWQgPSBwcm9ncmVzc0V2ZW50ID0+IHtcbiAgICAgICAgY29uc3QgbG9hZGVkID0gcHJvZ3Jlc3NFdmVudC5sb2FkZWQ7XG4gICAgICAgIGNvbnN0IHRvdGFsID0gcHJvZ3Jlc3NFdmVudC5sZW5ndGhDb21wdXRhYmxlID8gcHJvZ3Jlc3NFdmVudC50b3RhbCA6IC0xO1xuICAgICAgICBpZiAodGhpcy5wcm9ncmVzc0NhbGxiYWNrXyAhPT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMucHJvZ3Jlc3NDYWxsYmFja18obG9hZGVkLCB0b3RhbCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBpZiAodGhpcy5wcm9ncmVzc0NhbGxiYWNrXyAhPT0gbnVsbCkge1xuICAgICAgICBjb25uZWN0aW9uLmFkZFVwbG9hZFByb2dyZXNzTGlzdGVuZXIocHJvZ3Jlc3NMaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIC8vIGNvbm5lY3Rpb24uc2VuZCgpIG5ldmVyIHJlamVjdHMsIHNvIHdlIGRvbid0IG5lZWQgdG8gaGF2ZSBhIGVycm9yIGhhbmRsZXIgb3IgdXNlIGNhdGNoIG9uIHRoZSByZXR1cm5lZCBwcm9taXNlLlxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICAgICAgY29ubmVjdGlvblxuICAgICAgICAuc2VuZChcbiAgICAgICAgICB0aGlzLnVybF8sXG4gICAgICAgICAgdGhpcy5tZXRob2RfLFxuICAgICAgICAgIHRoaXMuaXNVc2luZ0VtdWxhdG9yLFxuICAgICAgICAgIHRoaXMuYm9keV8sXG4gICAgICAgICAgdGhpcy5oZWFkZXJzX1xuICAgICAgICApXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5wcm9ncmVzc0NhbGxiYWNrXyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29ubmVjdGlvbi5yZW1vdmVVcGxvYWRQcm9ncmVzc0xpc3RlbmVyKHByb2dyZXNzTGlzdGVuZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnBlbmRpbmdDb25uZWN0aW9uXyA9IG51bGw7XG4gICAgICAgICAgY29uc3QgaGl0U2VydmVyID0gY29ubmVjdGlvbi5nZXRFcnJvckNvZGUoKSA9PT0gRXJyb3JDb2RlLk5PX0VSUk9SO1xuICAgICAgICAgIGNvbnN0IHN0YXR1cyA9IGNvbm5lY3Rpb24uZ2V0U3RhdHVzKCk7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgIWhpdFNlcnZlciB8fFxuICAgICAgICAgICAgKGlzUmV0cnlTdGF0dXNDb2RlKHN0YXR1cywgdGhpcy5hZGRpdGlvbmFsUmV0cnlDb2Rlc18pICYmXG4gICAgICAgICAgICAgIHRoaXMucmV0cnkpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCB3YXNDYW5jZWxlZCA9IGNvbm5lY3Rpb24uZ2V0RXJyb3JDb2RlKCkgPT09IEVycm9yQ29kZS5BQk9SVDtcbiAgICAgICAgICAgIGJhY2tvZmZDYWxsYmFjayhcbiAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICAgIG5ldyBSZXF1ZXN0RW5kU3RhdHVzKGZhbHNlLCBudWxsLCB3YXNDYW5jZWxlZClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHN1Y2Nlc3NDb2RlID0gdGhpcy5zdWNjZXNzQ29kZXNfLmluZGV4T2Yoc3RhdHVzKSAhPT0gLTE7XG4gICAgICAgICAgYmFja29mZkNhbGxiYWNrKHRydWUsIG5ldyBSZXF1ZXN0RW5kU3RhdHVzKHN1Y2Nlc3NDb2RlLCBjb25uZWN0aW9uKSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gcmVxdWVzdFdlbnRUaHJvdWdoIC0gVHJ1ZSBpZiB0aGUgcmVxdWVzdCBldmVudHVhbGx5IHdlbnRcbiAgICAgKiAgICAgdGhyb3VnaCwgZmFsc2UgaWYgaXQgaGl0IHRoZSByZXRyeSBsaW1pdCBvciB3YXMgY2FuY2VsZWQuXG4gICAgICovXG4gICAgY29uc3QgYmFja29mZkRvbmU6IChcbiAgICAgIHJlcXVlc3RXZW50VGhyb3VnaDogYm9vbGVhbixcbiAgICAgIHN0YXR1czogUmVxdWVzdEVuZFN0YXR1czxJPlxuICAgICkgPT4gdm9pZCA9IChyZXF1ZXN0V2VudFRocm91Z2gsIHN0YXR1cykgPT4ge1xuICAgICAgY29uc3QgcmVzb2x2ZSA9IHRoaXMucmVzb2x2ZV87XG4gICAgICBjb25zdCByZWplY3QgPSB0aGlzLnJlamVjdF87XG4gICAgICBjb25zdCBjb25uZWN0aW9uID0gc3RhdHVzLmNvbm5lY3Rpb24gYXMgQ29ubmVjdGlvbjxJPjtcbiAgICAgIGlmIChzdGF0dXMud2FzU3VjY2Vzc0NvZGUpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmNhbGxiYWNrXyhjb25uZWN0aW9uLCBjb25uZWN0aW9uLmdldFJlc3BvbnNlKCkpO1xuICAgICAgICAgIGlmIChpc0p1c3REZWYocmVzdWx0KSkge1xuICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoY29ubmVjdGlvbiAhPT0gbnVsbCkge1xuICAgICAgICAgIGNvbnN0IGVyciA9IHVua25vd24oKTtcbiAgICAgICAgICBlcnIuc2VydmVyUmVzcG9uc2UgPSBjb25uZWN0aW9uLmdldEVycm9yVGV4dCgpO1xuICAgICAgICAgIGlmICh0aGlzLmVycm9yQ2FsbGJhY2tfKSB7XG4gICAgICAgICAgICByZWplY3QodGhpcy5lcnJvckNhbGxiYWNrXyhjb25uZWN0aW9uLCBlcnIpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChzdGF0dXMuY2FuY2VsZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGVyciA9IHRoaXMuYXBwRGVsZXRlXyA/IGFwcERlbGV0ZWQoKSA6IGNhbmNlbGVkKCk7XG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZXJyID0gcmV0cnlMaW1pdEV4Y2VlZGVkKCk7XG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIGlmICh0aGlzLmNhbmNlbGVkXykge1xuICAgICAgYmFja29mZkRvbmUoZmFsc2UsIG5ldyBSZXF1ZXN0RW5kU3RhdHVzKGZhbHNlLCBudWxsLCB0cnVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYmFja29mZklkXyA9IHN0YXJ0KGRvVGhlUmVxdWVzdCwgYmFja29mZkRvbmUsIHRoaXMudGltZW91dF8pO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBnZXRQcm9taXNlKCk6IFByb21pc2U8Tz4ge1xuICAgIHJldHVybiB0aGlzLnByb21pc2VfO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGNhbmNlbChhcHBEZWxldGU/OiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5jYW5jZWxlZF8gPSB0cnVlO1xuICAgIHRoaXMuYXBwRGVsZXRlXyA9IGFwcERlbGV0ZSB8fCBmYWxzZTtcbiAgICBpZiAodGhpcy5iYWNrb2ZmSWRfICE9PSBudWxsKSB7XG4gICAgICBzdG9wKHRoaXMuYmFja29mZklkXyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnBlbmRpbmdDb25uZWN0aW9uXyAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5wZW5kaW5nQ29ubmVjdGlvbl8uYWJvcnQoKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBBIGNvbGxlY3Rpb24gb2YgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHJlc3VsdCBvZiBhIG5ldHdvcmsgcmVxdWVzdC5cbiAqIEBwYXJhbSBvcHRfY2FuY2VsZWQgLSBEZWZhdWx0cyB0byBmYWxzZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlcXVlc3RFbmRTdGF0dXM8SSBleHRlbmRzIENvbm5lY3Rpb25UeXBlPiB7XG4gIC8qKlxuICAgKiBUcnVlIGlmIHRoZSByZXF1ZXN0IHdhcyBjYW5jZWxlZC5cbiAgICovXG4gIGNhbmNlbGVkOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyB3YXNTdWNjZXNzQ29kZTogYm9vbGVhbixcbiAgICBwdWJsaWMgY29ubmVjdGlvbjogQ29ubmVjdGlvbjxJPiB8IG51bGwsXG4gICAgY2FuY2VsZWQ/OiBib29sZWFuXG4gICkge1xuICAgIHRoaXMuY2FuY2VsZWQgPSAhIWNhbmNlbGVkO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRBdXRoSGVhZGVyXyhcbiAgaGVhZGVyczogSGVhZGVycyxcbiAgYXV0aFRva2VuOiBzdHJpbmcgfCBudWxsXG4pOiB2b2lkIHtcbiAgaWYgKGF1dGhUb2tlbiAhPT0gbnVsbCAmJiBhdXRoVG9rZW4ubGVuZ3RoID4gMCkge1xuICAgIGhlYWRlcnNbJ0F1dGhvcml6YXRpb24nXSA9ICdGaXJlYmFzZSAnICsgYXV0aFRva2VuO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRWZXJzaW9uSGVhZGVyXyhcbiAgaGVhZGVyczogSGVhZGVycyxcbiAgZmlyZWJhc2VWZXJzaW9uPzogc3RyaW5nXG4pOiB2b2lkIHtcbiAgaGVhZGVyc1snWC1GaXJlYmFzZS1TdG9yYWdlLVZlcnNpb24nXSA9XG4gICAgJ3dlYmpzLycgKyAoZmlyZWJhc2VWZXJzaW9uID8/ICdBcHBNYW5hZ2VyJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRHbXBpZEhlYWRlcl8oaGVhZGVyczogSGVhZGVycywgYXBwSWQ6IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgaWYgKGFwcElkKSB7XG4gICAgaGVhZGVyc1snWC1GaXJlYmFzZS1HTVBJRCddID0gYXBwSWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZEFwcENoZWNrSGVhZGVyXyhcbiAgaGVhZGVyczogSGVhZGVycyxcbiAgYXBwQ2hlY2tUb2tlbjogc3RyaW5nIHwgbnVsbFxuKTogdm9pZCB7XG4gIGlmIChhcHBDaGVja1Rva2VuICE9PSBudWxsKSB7XG4gICAgaGVhZGVyc1snWC1GaXJlYmFzZS1BcHBDaGVjayddID0gYXBwQ2hlY2tUb2tlbjtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFrZVJlcXVlc3Q8SSBleHRlbmRzIENvbm5lY3Rpb25UeXBlLCBPPihcbiAgcmVxdWVzdEluZm86IFJlcXVlc3RJbmZvPEksIE8+LFxuICBhcHBJZDogc3RyaW5nIHwgbnVsbCxcbiAgYXV0aFRva2VuOiBzdHJpbmcgfCBudWxsLFxuICBhcHBDaGVja1Rva2VuOiBzdHJpbmcgfCBudWxsLFxuICByZXF1ZXN0RmFjdG9yeTogKCkgPT4gQ29ubmVjdGlvbjxJPixcbiAgZmlyZWJhc2VWZXJzaW9uPzogc3RyaW5nLFxuICByZXRyeSA9IHRydWUsXG4gIGlzVXNpbmdFbXVsYXRvciA9IGZhbHNlXG4pOiBSZXF1ZXN0PE8+IHtcbiAgY29uc3QgcXVlcnlQYXJ0ID0gbWFrZVF1ZXJ5U3RyaW5nKHJlcXVlc3RJbmZvLnVybFBhcmFtcyk7XG4gIGNvbnN0IHVybCA9IHJlcXVlc3RJbmZvLnVybCArIHF1ZXJ5UGFydDtcbiAgY29uc3QgaGVhZGVycyA9IE9iamVjdC5hc3NpZ24oe30sIHJlcXVlc3RJbmZvLmhlYWRlcnMpO1xuICBhZGRHbXBpZEhlYWRlcl8oaGVhZGVycywgYXBwSWQpO1xuICBhZGRBdXRoSGVhZGVyXyhoZWFkZXJzLCBhdXRoVG9rZW4pO1xuICBhZGRWZXJzaW9uSGVhZGVyXyhoZWFkZXJzLCBmaXJlYmFzZVZlcnNpb24pO1xuICBhZGRBcHBDaGVja0hlYWRlcl8oaGVhZGVycywgYXBwQ2hlY2tUb2tlbik7XG4gIHJldHVybiBuZXcgTmV0d29ya1JlcXVlc3Q8SSwgTz4oXG4gICAgdXJsLFxuICAgIHJlcXVlc3RJbmZvLm1ldGhvZCxcbiAgICBoZWFkZXJzLFxuICAgIHJlcXVlc3RJbmZvLmJvZHksXG4gICAgcmVxdWVzdEluZm8uc3VjY2Vzc0NvZGVzLFxuICAgIHJlcXVlc3RJbmZvLmFkZGl0aW9uYWxSZXRyeUNvZGVzLFxuICAgIHJlcXVlc3RJbmZvLmhhbmRsZXIsXG4gICAgcmVxdWVzdEluZm8uZXJyb3JIYW5kbGVyLFxuICAgIHJlcXVlc3RJbmZvLnRpbWVvdXQsXG4gICAgcmVxdWVzdEluZm8ucHJvZ3Jlc3NDYWxsYmFjayxcbiAgICByZXF1ZXN0RmFjdG9yeSxcbiAgICByZXRyeSxcbiAgICBpc1VzaW5nRW11bGF0b3JcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IFNvbWUgbWV0aG9kcyBjb3BpZWQgZnJvbSBnb29nLmZzLlxuICogV2UgZG9uJ3QgaW5jbHVkZSBnb29nLmZzIGJlY2F1c2UgaXQgcHVsbHMgaW4gYSBidW5jaCBvZiBEZWZlcnJlZCBjb2RlIHRoYXRcbiAqIGJsb2F0cyB0aGUgc2l6ZSBvZiB0aGUgcmVsZWFzZWQgYmluYXJ5LlxuICovXG5pbXBvcnQgeyBpc05hdGl2ZUJsb2JEZWZpbmVkIH0gZnJvbSAnLi90eXBlJztcbmltcG9ydCB7IFN0b3JhZ2VFcnJvckNvZGUsIFN0b3JhZ2VFcnJvciB9IGZyb20gJy4vZXJyb3InO1xuXG5mdW5jdGlvbiBnZXRCbG9iQnVpbGRlcigpOiB0eXBlb2YgSUJsb2JCdWlsZGVyIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHR5cGVvZiBCbG9iQnVpbGRlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gQmxvYkJ1aWxkZXI7XG4gIH0gZWxzZSBpZiAodHlwZW9mIFdlYktpdEJsb2JCdWlsZGVyICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBXZWJLaXRCbG9iQnVpbGRlcjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogQ29uY2F0ZW5hdGVzIG9uZSBvciBtb3JlIHZhbHVlcyB0b2dldGhlciBhbmQgY29udmVydHMgdGhlbSB0byBhIEJsb2IuXG4gKlxuICogQHBhcmFtIGFyZ3MgVGhlIHZhbHVlcyB0aGF0IHdpbGwgbWFrZSB1cCB0aGUgcmVzdWx0aW5nIGJsb2IuXG4gKiBAcmV0dXJuIFRoZSBibG9iLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QmxvYiguLi5hcmdzOiBBcnJheTxzdHJpbmcgfCBCbG9iIHwgQXJyYXlCdWZmZXI+KTogQmxvYiB7XG4gIGNvbnN0IEJsb2JCdWlsZGVyID0gZ2V0QmxvYkJ1aWxkZXIoKTtcbiAgaWYgKEJsb2JCdWlsZGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBiYiA9IG5ldyBCbG9iQnVpbGRlcigpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgYmIuYXBwZW5kKGFyZ3NbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gYmIuZ2V0QmxvYigpO1xuICB9IGVsc2Uge1xuICAgIGlmIChpc05hdGl2ZUJsb2JEZWZpbmVkKCkpIHtcbiAgICAgIHJldHVybiBuZXcgQmxvYihhcmdzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFN0b3JhZ2VFcnJvcihcbiAgICAgICAgU3RvcmFnZUVycm9yQ29kZS5VTlNVUFBPUlRFRF9FTlZJUk9OTUVOVCxcbiAgICAgICAgXCJUaGlzIGJyb3dzZXIgZG9lc24ndCBzZWVtIHRvIHN1cHBvcnQgY3JlYXRpbmcgQmxvYnNcIlxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBTbGljZXMgdGhlIGJsb2IuIFRoZSByZXR1cm5lZCBibG9iIGNvbnRhaW5zIGRhdGEgZnJvbSB0aGUgc3RhcnQgYnl0ZVxuICogKGluY2x1c2l2ZSkgdGlsbCB0aGUgZW5kIGJ5dGUgKGV4Y2x1c2l2ZSkuIE5lZ2F0aXZlIGluZGljZXMgY2Fubm90IGJlIHVzZWQuXG4gKlxuICogQHBhcmFtIGJsb2IgVGhlIGJsb2IgdG8gYmUgc2xpY2VkLlxuICogQHBhcmFtIHN0YXJ0IEluZGV4IG9mIHRoZSBzdGFydGluZyBieXRlLlxuICogQHBhcmFtIGVuZCBJbmRleCBvZiB0aGUgZW5kaW5nIGJ5dGUuXG4gKiBAcmV0dXJuIFRoZSBibG9iIHNsaWNlIG9yIG51bGwgaWYgbm90IHN1cHBvcnRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNsaWNlQmxvYihibG9iOiBCbG9iLCBzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IEJsb2IgfCBudWxsIHtcbiAgaWYgKGJsb2Iud2Via2l0U2xpY2UpIHtcbiAgICByZXR1cm4gYmxvYi53ZWJraXRTbGljZShzdGFydCwgZW5kKTtcbiAgfSBlbHNlIGlmIChibG9iLm1velNsaWNlKSB7XG4gICAgcmV0dXJuIGJsb2IubW96U2xpY2Uoc3RhcnQsIGVuZCk7XG4gIH0gZWxzZSBpZiAoYmxvYi5zbGljZSkge1xuICAgIHJldHVybiBibG9iLnNsaWNlKHN0YXJ0LCBlbmQpO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFRleHREZWNvZGVyIH0gZnJvbSAndXRpbCc7XG5pbXBvcnQgeyBpbnZhbGlkRm9ybWF0IH0gZnJvbSAnLi4vLi4vaW1wbGVtZW50YXRpb24vZXJyb3InO1xuXG4vKiogQ29udmVydHMgYSBCYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gYSBiaW5hcnkgc3RyaW5nLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUJhc2U2NChlbmNvZGVkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAvLyBOb2RlIGFjdHVhbGx5IGRvZXNuJ3QgdmFsaWRhdGUgYmFzZTY0IHN0cmluZ3MuXG4gIC8vIEEgcXVpY2sgc2FuaXR5IGNoZWNrIHRoYXQgaXMgbm90IGEgZm9vbC1wcm9vZiB2YWxpZGF0aW9uXG4gIGlmICgvW14tQS1aYS16MC05Ky89XS8udGVzdChlbmNvZGVkKSkge1xuICAgIHRocm93IGludmFsaWRGb3JtYXQoJ2Jhc2U2NCcsICdJbnZhbGlkIGNoYXJhY3RlciBmb3VuZCcpO1xuICB9XG4gIHJldHVybiBCdWZmZXIuZnJvbShlbmNvZGVkLCAnYmFzZTY0JykudG9TdHJpbmcoJ2JpbmFyeScpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlVWludDhBcnJheShkYXRhOiBVaW50OEFycmF5KTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShkYXRhKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyB1bmtub3duLCBpbnZhbGlkRm9ybWF0IH0gZnJvbSAnLi9lcnJvcic7XG5pbXBvcnQgeyBkZWNvZGVCYXNlNjQgfSBmcm9tICcuLi9wbGF0Zm9ybS9iYXNlNjQnO1xuXG4vKipcbiAqIEFuIGVudW1lcmF0aW9uIG9mIHRoZSBwb3NzaWJsZSBzdHJpbmcgZm9ybWF0cyBmb3IgdXBsb2FkLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgdHlwZSBTdHJpbmdGb3JtYXQgPSAodHlwZW9mIFN0cmluZ0Zvcm1hdClba2V5b2YgdHlwZW9mIFN0cmluZ0Zvcm1hdF07XG4vKipcbiAqIEFuIGVudW1lcmF0aW9uIG9mIHRoZSBwb3NzaWJsZSBzdHJpbmcgZm9ybWF0cyBmb3IgdXBsb2FkLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgU3RyaW5nRm9ybWF0ID0ge1xuICAvKipcbiAgICogSW5kaWNhdGVzIHRoZSBzdHJpbmcgc2hvdWxkIGJlIGludGVycHJldGVkIFwicmF3XCIsIHRoYXQgaXMsIGFzIG5vcm1hbCB0ZXh0LlxuICAgKiBUaGUgc3RyaW5nIHdpbGwgYmUgaW50ZXJwcmV0ZWQgYXMgVVRGLTE2LCB0aGVuIHVwbG9hZGVkIGFzIGEgVVRGLTggYnl0ZVxuICAgKiBzZXF1ZW5jZS5cbiAgICogRXhhbXBsZTogVGhlIHN0cmluZyAnSGVsbG8hIFxcXFx1ZDgzZFxcXFx1ZGUwYScgYmVjb21lcyB0aGUgYnl0ZSBzZXF1ZW5jZVxuICAgKiA0OCA2NSA2YyA2YyA2ZiAyMSAyMCBmMCA5ZiA5OCA4YVxuICAgKi9cbiAgUkFXOiAncmF3JyxcbiAgLyoqXG4gICAqIEluZGljYXRlcyB0aGUgc3RyaW5nIHNob3VsZCBiZSBpbnRlcnByZXRlZCBhcyBiYXNlNjQtZW5jb2RlZCBkYXRhLlxuICAgKiBQYWRkaW5nIGNoYXJhY3RlcnMgKHRyYWlsaW5nICc9J3MpIGFyZSBvcHRpb25hbC5cbiAgICogRXhhbXBsZTogVGhlIHN0cmluZyAncldtTysrRTZ0Ny9ybHc9PScgYmVjb21lcyB0aGUgYnl0ZSBzZXF1ZW5jZVxuICAgKiBhZCA2OSA4ZSBmYiBlMSAzYSBiNyBiZiBlYiA5N1xuICAgKi9cbiAgQkFTRTY0OiAnYmFzZTY0JyxcbiAgLyoqXG4gICAqIEluZGljYXRlcyB0aGUgc3RyaW5nIHNob3VsZCBiZSBpbnRlcnByZXRlZCBhcyBiYXNlNjR1cmwtZW5jb2RlZCBkYXRhLlxuICAgKiBQYWRkaW5nIGNoYXJhY3RlcnMgKHRyYWlsaW5nICc9J3MpIGFyZSBvcHRpb25hbC5cbiAgICogRXhhbXBsZTogVGhlIHN0cmluZyAncldtTy0tRTZ0N19ybHc9PScgYmVjb21lcyB0aGUgYnl0ZSBzZXF1ZW5jZVxuICAgKiBhZCA2OSA4ZSBmYiBlMSAzYSBiNyBiZiBlYiA5N1xuICAgKi9cbiAgQkFTRTY0VVJMOiAnYmFzZTY0dXJsJyxcbiAgLyoqXG4gICAqIEluZGljYXRlcyB0aGUgc3RyaW5nIGlzIGEgZGF0YSBVUkwsIHN1Y2ggYXMgb25lIG9idGFpbmVkIGZyb21cbiAgICogY2FudmFzLnRvRGF0YVVSTCgpLlxuICAgKiBFeGFtcGxlOiB0aGUgc3RyaW5nICdkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsYWFhYSdcbiAgICogYmVjb21lcyB0aGUgYnl0ZSBzZXF1ZW5jZVxuICAgKiA2OSBhNiA5YVxuICAgKiAodGhlIGNvbnRlbnQtdHlwZSBcImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbVwiIGlzIGFsc28gYXBwbGllZCwgYnV0IGNhblxuICAgKiBiZSBvdmVycmlkZGVuIGluIHRoZSBtZXRhZGF0YSBvYmplY3QpLlxuICAgKi9cbiAgREFUQV9VUkw6ICdkYXRhX3VybCdcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBjbGFzcyBTdHJpbmdEYXRhIHtcbiAgY29udGVudFR5cGU6IHN0cmluZyB8IG51bGw7XG5cbiAgY29uc3RydWN0b3IocHVibGljIGRhdGE6IFVpbnQ4QXJyYXksIGNvbnRlbnRUeXBlPzogc3RyaW5nIHwgbnVsbCkge1xuICAgIHRoaXMuY29udGVudFR5cGUgPSBjb250ZW50VHlwZSB8fCBudWxsO1xuICB9XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkYXRhRnJvbVN0cmluZyhcbiAgZm9ybWF0OiBTdHJpbmdGb3JtYXQsXG4gIHN0cmluZ0RhdGE6IHN0cmluZ1xuKTogU3RyaW5nRGF0YSB7XG4gIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgY2FzZSBTdHJpbmdGb3JtYXQuUkFXOlxuICAgICAgcmV0dXJuIG5ldyBTdHJpbmdEYXRhKHV0ZjhCeXRlc18oc3RyaW5nRGF0YSkpO1xuICAgIGNhc2UgU3RyaW5nRm9ybWF0LkJBU0U2NDpcbiAgICBjYXNlIFN0cmluZ0Zvcm1hdC5CQVNFNjRVUkw6XG4gICAgICByZXR1cm4gbmV3IFN0cmluZ0RhdGEoYmFzZTY0Qnl0ZXNfKGZvcm1hdCwgc3RyaW5nRGF0YSkpO1xuICAgIGNhc2UgU3RyaW5nRm9ybWF0LkRBVEFfVVJMOlxuICAgICAgcmV0dXJuIG5ldyBTdHJpbmdEYXRhKFxuICAgICAgICBkYXRhVVJMQnl0ZXNfKHN0cmluZ0RhdGEpLFxuICAgICAgICBkYXRhVVJMQ29udGVudFR5cGVfKHN0cmluZ0RhdGEpXG4gICAgICApO1xuICAgIGRlZmF1bHQ6XG4gICAgLy8gZG8gbm90aGluZ1xuICB9XG5cbiAgLy8gYXNzZXJ0KGZhbHNlKTtcbiAgdGhyb3cgdW5rbm93bigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdXRmOEJ5dGVzXyh2YWx1ZTogc3RyaW5nKTogVWludDhBcnJheSB7XG4gIGNvbnN0IGI6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgYyA9IHZhbHVlLmNoYXJDb2RlQXQoaSk7XG4gICAgaWYgKGMgPD0gMTI3KSB7XG4gICAgICBiLnB1c2goYyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChjIDw9IDIwNDcpIHtcbiAgICAgICAgYi5wdXNoKDE5MiB8IChjID4+IDYpLCAxMjggfCAoYyAmIDYzKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoKGMgJiA2NDUxMikgPT09IDU1Mjk2KSB7XG4gICAgICAgICAgLy8gVGhlIHN0YXJ0IG9mIGEgc3Vycm9nYXRlIHBhaXIuXG4gICAgICAgICAgY29uc3QgdmFsaWQgPVxuICAgICAgICAgICAgaSA8IHZhbHVlLmxlbmd0aCAtIDEgJiYgKHZhbHVlLmNoYXJDb2RlQXQoaSArIDEpICYgNjQ1MTIpID09PSA1NjMyMDtcbiAgICAgICAgICBpZiAoIXZhbGlkKSB7XG4gICAgICAgICAgICAvLyBUaGUgc2Vjb25kIHN1cnJvZ2F0ZSB3YXNuJ3QgdGhlcmUuXG4gICAgICAgICAgICBiLnB1c2goMjM5LCAxOTEsIDE4OSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGhpID0gYztcbiAgICAgICAgICAgIGNvbnN0IGxvID0gdmFsdWUuY2hhckNvZGVBdCgrK2kpO1xuICAgICAgICAgICAgYyA9IDY1NTM2IHwgKChoaSAmIDEwMjMpIDw8IDEwKSB8IChsbyAmIDEwMjMpO1xuICAgICAgICAgICAgYi5wdXNoKFxuICAgICAgICAgICAgICAyNDAgfCAoYyA+PiAxOCksXG4gICAgICAgICAgICAgIDEyOCB8ICgoYyA+PiAxMikgJiA2MyksXG4gICAgICAgICAgICAgIDEyOCB8ICgoYyA+PiA2KSAmIDYzKSxcbiAgICAgICAgICAgICAgMTI4IHwgKGMgJiA2MylcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICgoYyAmIDY0NTEyKSA9PT0gNTYzMjApIHtcbiAgICAgICAgICAgIC8vIEludmFsaWQgbG93IHN1cnJvZ2F0ZS5cbiAgICAgICAgICAgIGIucHVzaCgyMzksIDE5MSwgMTg5KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYi5wdXNoKDIyNCB8IChjID4+IDEyKSwgMTI4IHwgKChjID4+IDYpICYgNjMpLCAxMjggfCAoYyAmIDYzKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBuZXcgVWludDhBcnJheShiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBlcmNlbnRFbmNvZGVkQnl0ZXNfKHZhbHVlOiBzdHJpbmcpOiBVaW50OEFycmF5IHtcbiAgbGV0IGRlY29kZWQ7XG4gIHRyeSB7XG4gICAgZGVjb2RlZCA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBpbnZhbGlkRm9ybWF0KFN0cmluZ0Zvcm1hdC5EQVRBX1VSTCwgJ01hbGZvcm1lZCBkYXRhIFVSTC4nKTtcbiAgfVxuICByZXR1cm4gdXRmOEJ5dGVzXyhkZWNvZGVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJhc2U2NEJ5dGVzXyhmb3JtYXQ6IFN0cmluZ0Zvcm1hdCwgdmFsdWU6IHN0cmluZyk6IFVpbnQ4QXJyYXkge1xuICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgIGNhc2UgU3RyaW5nRm9ybWF0LkJBU0U2NDoge1xuICAgICAgY29uc3QgaGFzTWludXMgPSB2YWx1ZS5pbmRleE9mKCctJykgIT09IC0xO1xuICAgICAgY29uc3QgaGFzVW5kZXIgPSB2YWx1ZS5pbmRleE9mKCdfJykgIT09IC0xO1xuICAgICAgaWYgKGhhc01pbnVzIHx8IGhhc1VuZGVyKSB7XG4gICAgICAgIGNvbnN0IGludmFsaWRDaGFyID0gaGFzTWludXMgPyAnLScgOiAnXyc7XG4gICAgICAgIHRocm93IGludmFsaWRGb3JtYXQoXG4gICAgICAgICAgZm9ybWF0LFxuICAgICAgICAgIFwiSW52YWxpZCBjaGFyYWN0ZXIgJ1wiICtcbiAgICAgICAgICAgIGludmFsaWRDaGFyICtcbiAgICAgICAgICAgIFwiJyBmb3VuZDogaXMgaXQgYmFzZTY0dXJsIGVuY29kZWQ/XCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjYXNlIFN0cmluZ0Zvcm1hdC5CQVNFNjRVUkw6IHtcbiAgICAgIGNvbnN0IGhhc1BsdXMgPSB2YWx1ZS5pbmRleE9mKCcrJykgIT09IC0xO1xuICAgICAgY29uc3QgaGFzU2xhc2ggPSB2YWx1ZS5pbmRleE9mKCcvJykgIT09IC0xO1xuICAgICAgaWYgKGhhc1BsdXMgfHwgaGFzU2xhc2gpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZENoYXIgPSBoYXNQbHVzID8gJysnIDogJy8nO1xuICAgICAgICB0aHJvdyBpbnZhbGlkRm9ybWF0KFxuICAgICAgICAgIGZvcm1hdCxcbiAgICAgICAgICBcIkludmFsaWQgY2hhcmFjdGVyICdcIiArIGludmFsaWRDaGFyICsgXCInIGZvdW5kOiBpcyBpdCBiYXNlNjQgZW5jb2RlZD9cIlxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC8tL2csICcrJykucmVwbGFjZSgvXy9nLCAnLycpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGRlZmF1bHQ6XG4gICAgLy8gZG8gbm90aGluZ1xuICB9XG4gIGxldCBieXRlcztcbiAgdHJ5IHtcbiAgICBieXRlcyA9IGRlY29kZUJhc2U2NCh2YWx1ZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoKGUgYXMgRXJyb3IpLm1lc3NhZ2UuaW5jbHVkZXMoJ3BvbHlmaWxsJykpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIHRocm93IGludmFsaWRGb3JtYXQoZm9ybWF0LCAnSW52YWxpZCBjaGFyYWN0ZXIgZm91bmQnKTtcbiAgfVxuICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KGJ5dGVzLmxlbmd0aCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICBhcnJheVtpXSA9IGJ5dGVzLmNoYXJDb2RlQXQoaSk7XG4gIH1cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5jbGFzcyBEYXRhVVJMUGFydHMge1xuICBiYXNlNjQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgY29udGVudFR5cGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICByZXN0OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoZGF0YVVSTDogc3RyaW5nKSB7XG4gICAgY29uc3QgbWF0Y2hlcyA9IGRhdGFVUkwubWF0Y2goL15kYXRhOihbXixdKyk/LC8pO1xuICAgIGlmIChtYXRjaGVzID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBpbnZhbGlkRm9ybWF0KFxuICAgICAgICBTdHJpbmdGb3JtYXQuREFUQV9VUkwsXG4gICAgICAgIFwiTXVzdCBiZSBmb3JtYXR0ZWQgJ2RhdGE6WzxtZWRpYXR5cGU+XVs7YmFzZTY0XSw8ZGF0YT5cIlxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgbWlkZGxlID0gbWF0Y2hlc1sxXSB8fCBudWxsO1xuICAgIGlmIChtaWRkbGUgIT0gbnVsbCkge1xuICAgICAgdGhpcy5iYXNlNjQgPSBlbmRzV2l0aChtaWRkbGUsICc7YmFzZTY0Jyk7XG4gICAgICB0aGlzLmNvbnRlbnRUeXBlID0gdGhpcy5iYXNlNjRcbiAgICAgICAgPyBtaWRkbGUuc3Vic3RyaW5nKDAsIG1pZGRsZS5sZW5ndGggLSAnO2Jhc2U2NCcubGVuZ3RoKVxuICAgICAgICA6IG1pZGRsZTtcbiAgICB9XG4gICAgdGhpcy5yZXN0ID0gZGF0YVVSTC5zdWJzdHJpbmcoZGF0YVVSTC5pbmRleE9mKCcsJykgKyAxKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGF0YVVSTEJ5dGVzXyhkYXRhVXJsOiBzdHJpbmcpOiBVaW50OEFycmF5IHtcbiAgY29uc3QgcGFydHMgPSBuZXcgRGF0YVVSTFBhcnRzKGRhdGFVcmwpO1xuICBpZiAocGFydHMuYmFzZTY0KSB7XG4gICAgcmV0dXJuIGJhc2U2NEJ5dGVzXyhTdHJpbmdGb3JtYXQuQkFTRTY0LCBwYXJ0cy5yZXN0KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcGVyY2VudEVuY29kZWRCeXRlc18ocGFydHMucmVzdCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRhdGFVUkxDb250ZW50VHlwZV8oZGF0YVVybDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IHBhcnRzID0gbmV3IERhdGFVUkxQYXJ0cyhkYXRhVXJsKTtcbiAgcmV0dXJuIHBhcnRzLmNvbnRlbnRUeXBlO1xufVxuXG5mdW5jdGlvbiBlbmRzV2l0aChzOiBzdHJpbmcsIGVuZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGxvbmdFbm91Z2ggPSBzLmxlbmd0aCA+PSBlbmQubGVuZ3RoO1xuICBpZiAoIWxvbmdFbm91Z2gpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gcy5zdWJzdHJpbmcocy5sZW5ndGggLSBlbmQubGVuZ3RoKSA9PT0gZW5kO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQGZpbGUgUHJvdmlkZXMgYSBCbG9iLWxpa2Ugd3JhcHBlciBmb3IgdmFyaW91cyBiaW5hcnkgdHlwZXMgKGluY2x1ZGluZyB0aGVcbiAqIG5hdGl2ZSBCbG9iIHR5cGUpLiBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvIHVwbG9hZCB0eXBlcyBsaWtlIEFycmF5QnVmZmVycyxcbiAqIG1ha2luZyB1cGxvYWRzIHBvc3NpYmxlIGluIGVudmlyb25tZW50cyB3aXRob3V0IHRoZSBuYXRpdmUgQmxvYiB0eXBlLlxuICovXG5pbXBvcnQgeyBzbGljZUJsb2IsIGdldEJsb2IgfSBmcm9tICcuL2ZzJztcbmltcG9ydCB7IFN0cmluZ0Zvcm1hdCwgZGF0YUZyb21TdHJpbmcgfSBmcm9tICcuL3N0cmluZyc7XG5pbXBvcnQgeyBpc05hdGl2ZUJsb2IsIGlzTmF0aXZlQmxvYkRlZmluZWQsIGlzU3RyaW5nIH0gZnJvbSAnLi90eXBlJztcblxuLyoqXG4gKiBAcGFyYW0gb3B0X2VsaWRlQ29weSAtIElmIHRydWUsIGRvZXNuJ3QgY29weSBtdXRhYmxlIGlucHV0IGRhdGFcbiAqICAgICAoZS5nLiBVaW50OEFycmF5cykuIFBhc3MgdHJ1ZSBvbmx5IGlmIHlvdSBrbm93IHRoZSBvYmplY3RzIHdpbGwgbm90IGJlXG4gKiAgICAgbW9kaWZpZWQgYWZ0ZXIgdGhpcyBibG9iJ3MgY29uc3RydWN0aW9uLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY2xhc3MgRmJzQmxvYiB7XG4gIHByaXZhdGUgZGF0YV8hOiBCbG9iIHwgVWludDhBcnJheTtcbiAgcHJpdmF0ZSBzaXplXzogbnVtYmVyO1xuICBwcml2YXRlIHR5cGVfOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoZGF0YTogQmxvYiB8IFVpbnQ4QXJyYXkgfCBBcnJheUJ1ZmZlciwgZWxpZGVDb3B5PzogYm9vbGVhbikge1xuICAgIGxldCBzaXplOiBudW1iZXIgPSAwO1xuICAgIGxldCBibG9iVHlwZTogc3RyaW5nID0gJyc7XG4gICAgaWYgKGlzTmF0aXZlQmxvYihkYXRhKSkge1xuICAgICAgdGhpcy5kYXRhXyA9IGRhdGEgYXMgQmxvYjtcbiAgICAgIHNpemUgPSAoZGF0YSBhcyBCbG9iKS5zaXplO1xuICAgICAgYmxvYlR5cGUgPSAoZGF0YSBhcyBCbG9iKS50eXBlO1xuICAgIH0gZWxzZSBpZiAoZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICBpZiAoZWxpZGVDb3B5KSB7XG4gICAgICAgIHRoaXMuZGF0YV8gPSBuZXcgVWludDhBcnJheShkYXRhKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZGF0YV8gPSBuZXcgVWludDhBcnJheShkYXRhLmJ5dGVMZW5ndGgpO1xuICAgICAgICB0aGlzLmRhdGFfLnNldChuZXcgVWludDhBcnJheShkYXRhKSk7XG4gICAgICB9XG4gICAgICBzaXplID0gdGhpcy5kYXRhXy5sZW5ndGg7XG4gICAgfSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgaWYgKGVsaWRlQ29weSkge1xuICAgICAgICB0aGlzLmRhdGFfID0gZGF0YSBhcyBVaW50OEFycmF5O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kYXRhXyA9IG5ldyBVaW50OEFycmF5KGRhdGEubGVuZ3RoKTtcbiAgICAgICAgdGhpcy5kYXRhXy5zZXQoZGF0YSBhcyBVaW50OEFycmF5KTtcbiAgICAgIH1cbiAgICAgIHNpemUgPSBkYXRhLmxlbmd0aDtcbiAgICB9XG4gICAgdGhpcy5zaXplXyA9IHNpemU7XG4gICAgdGhpcy50eXBlXyA9IGJsb2JUeXBlO1xuICB9XG5cbiAgc2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnNpemVfO1xuICB9XG5cbiAgdHlwZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnR5cGVfO1xuICB9XG5cbiAgc2xpY2Uoc3RhcnRCeXRlOiBudW1iZXIsIGVuZEJ5dGU6IG51bWJlcik6IEZic0Jsb2IgfCBudWxsIHtcbiAgICBpZiAoaXNOYXRpdmVCbG9iKHRoaXMuZGF0YV8pKSB7XG4gICAgICBjb25zdCByZWFsQmxvYiA9IHRoaXMuZGF0YV8gYXMgQmxvYjtcbiAgICAgIGNvbnN0IHNsaWNlZCA9IHNsaWNlQmxvYihyZWFsQmxvYiwgc3RhcnRCeXRlLCBlbmRCeXRlKTtcbiAgICAgIGlmIChzbGljZWQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEZic0Jsb2Ioc2xpY2VkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc2xpY2UgPSBuZXcgVWludDhBcnJheShcbiAgICAgICAgKHRoaXMuZGF0YV8gYXMgVWludDhBcnJheSkuYnVmZmVyLFxuICAgICAgICBzdGFydEJ5dGUsXG4gICAgICAgIGVuZEJ5dGUgLSBzdGFydEJ5dGVcbiAgICAgICk7XG4gICAgICByZXR1cm4gbmV3IEZic0Jsb2Ioc2xpY2UsIHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBnZXRCbG9iKC4uLmFyZ3M6IEFycmF5PHN0cmluZyB8IEZic0Jsb2I+KTogRmJzQmxvYiB8IG51bGwge1xuICAgIGlmIChpc05hdGl2ZUJsb2JEZWZpbmVkKCkpIHtcbiAgICAgIGNvbnN0IGJsb2JieTogQXJyYXk8QmxvYiB8IFVpbnQ4QXJyYXkgfCBzdHJpbmc+ID0gYXJncy5tYXAoXG4gICAgICAgICh2YWw6IHN0cmluZyB8IEZic0Jsb2IpOiBCbG9iIHwgVWludDhBcnJheSB8IHN0cmluZyA9PiB7XG4gICAgICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIEZic0Jsb2IpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWwuZGF0YV87XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgcmV0dXJuIG5ldyBGYnNCbG9iKGdldEJsb2IuYXBwbHkobnVsbCwgYmxvYmJ5KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHVpbnQ4QXJyYXlzOiBVaW50OEFycmF5W10gPSBhcmdzLm1hcChcbiAgICAgICAgKHZhbDogc3RyaW5nIHwgRmJzQmxvYik6IFVpbnQ4QXJyYXkgPT4ge1xuICAgICAgICAgIGlmIChpc1N0cmluZyh2YWwpKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0YUZyb21TdHJpbmcoU3RyaW5nRm9ybWF0LlJBVywgdmFsIGFzIHN0cmluZykuZGF0YTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gQmxvYnMgZG9uJ3QgZXhpc3QsIHNvIHRoaXMgaGFzIHRvIGJlIGEgVWludDhBcnJheS5cbiAgICAgICAgICAgIHJldHVybiAodmFsIGFzIEZic0Jsb2IpLmRhdGFfIGFzIFVpbnQ4QXJyYXk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgbGV0IGZpbmFsTGVuZ3RoID0gMDtcbiAgICAgIHVpbnQ4QXJyYXlzLmZvckVhY2goKGFycmF5OiBVaW50OEFycmF5KTogdm9pZCA9PiB7XG4gICAgICAgIGZpbmFsTGVuZ3RoICs9IGFycmF5LmJ5dGVMZW5ndGg7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IG1lcmdlZCA9IG5ldyBVaW50OEFycmF5KGZpbmFsTGVuZ3RoKTtcbiAgICAgIGxldCBpbmRleCA9IDA7XG4gICAgICB1aW50OEFycmF5cy5mb3JFYWNoKChhcnJheTogVWludDhBcnJheSkgPT4ge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgbWVyZ2VkW2luZGV4KytdID0gYXJyYXlbaV07XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5ldyBGYnNCbG9iKG1lcmdlZCwgdHJ1ZSk7XG4gICAgfVxuICB9XG5cbiAgdXBsb2FkRGF0YSgpOiBCbG9iIHwgVWludDhBcnJheSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YV87XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHsgaXNOb25BcnJheU9iamVjdCB9IGZyb20gJy4vdHlwZSc7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgT2JqZWN0IHJlc3VsdGluZyBmcm9tIHBhcnNpbmcgdGhlIGdpdmVuIEpTT04sIG9yIG51bGwgaWYgdGhlXG4gKiBnaXZlbiBzdHJpbmcgZG9lcyBub3QgcmVwcmVzZW50IGEgSlNPTiBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBqc29uT2JqZWN0T3JOdWxsKFxuICBzOiBzdHJpbmdcbik6IHsgW25hbWU6IHN0cmluZ106IHVua25vd24gfSB8IG51bGwge1xuICBsZXQgb2JqO1xuICB0cnkge1xuICAgIG9iaiA9IEpTT04ucGFyc2Uocyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBpZiAoaXNOb25BcnJheU9iamVjdChvYmopKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQGZpbGVvdmVydmlldyBDb250YWlucyBoZWxwZXIgbWV0aG9kcyBmb3IgbWFuaXB1bGF0aW5nIHBhdGhzLlxuICovXG5cbi8qKlxuICogQHJldHVybiBOdWxsIGlmIHRoZSBwYXRoIGlzIGFscmVhZHkgYXQgdGhlIHJvb3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJlbnQocGF0aDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmIChwYXRoLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IGluZGV4ID0gcGF0aC5sYXN0SW5kZXhPZignLycpO1xuICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG4gIGNvbnN0IG5ld1BhdGggPSBwYXRoLnNsaWNlKDAsIGluZGV4KTtcbiAgcmV0dXJuIG5ld1BhdGg7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGlsZChwYXRoOiBzdHJpbmcsIGNoaWxkUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgY2Fub25pY2FsQ2hpbGRQYXRoID0gY2hpbGRQYXRoXG4gICAgLnNwbGl0KCcvJylcbiAgICAuZmlsdGVyKGNvbXBvbmVudCA9PiBjb21wb25lbnQubGVuZ3RoID4gMClcbiAgICAuam9pbignLycpO1xuICBpZiAocGF0aC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gY2Fub25pY2FsQ2hpbGRQYXRoO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBwYXRoICsgJy8nICsgY2Fub25pY2FsQ2hpbGRQYXRoO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbGFzdCBjb21wb25lbnQgb2YgYSBwYXRoLlxuICogJy9mb28vYmFyJyAtPiAnYmFyJ1xuICogJy9mb28vYmFyL2Jhei8nIC0+ICdiYXovJ1xuICogJy9hJyAtPiAnYSdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhc3RDb21wb25lbnQocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgaW5kZXggPSBwYXRoLmxhc3RJbmRleE9mKCcvJywgcGF0aC5sZW5ndGggLSAyKTtcbiAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgIHJldHVybiBwYXRoO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBwYXRoLnNsaWNlKGluZGV4ICsgMSk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgRG9jdW1lbnRhdGlvbiBmb3IgdGhlIG1ldGFkYXRhIGZvcm1hdFxuICovXG5pbXBvcnQgeyBNZXRhZGF0YSB9IGZyb20gJy4uL21ldGFkYXRhJztcblxuaW1wb3J0IHsganNvbk9iamVjdE9yTnVsbCB9IGZyb20gJy4vanNvbic7XG5pbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJy4vbG9jYXRpb24nO1xuaW1wb3J0IHsgbGFzdENvbXBvbmVudCB9IGZyb20gJy4vcGF0aCc7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gJy4vdHlwZSc7XG5pbXBvcnQgeyBtYWtlVXJsLCBtYWtlUXVlcnlTdHJpbmcgfSBmcm9tICcuL3VybCc7XG5pbXBvcnQgeyBSZWZlcmVuY2UgfSBmcm9tICcuLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgRmlyZWJhc2VTdG9yYWdlSW1wbCB9IGZyb20gJy4uL3NlcnZpY2UnO1xuXG5leHBvcnQgZnVuY3Rpb24gbm9YZm9ybV88VD4obWV0YWRhdGE6IE1ldGFkYXRhLCB2YWx1ZTogVCk6IFQge1xuICByZXR1cm4gdmFsdWU7XG59XG5cbmNsYXNzIE1hcHBpbmc8VD4ge1xuICBsb2NhbDogc3RyaW5nO1xuICB3cml0YWJsZTogYm9vbGVhbjtcbiAgeGZvcm06IChwMTogTWV0YWRhdGEsIHAyPzogVCkgPT4gVCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgc2VydmVyOiBzdHJpbmcsXG4gICAgbG9jYWw/OiBzdHJpbmcgfCBudWxsLFxuICAgIHdyaXRhYmxlPzogYm9vbGVhbixcbiAgICB4Zm9ybT86ICgocDE6IE1ldGFkYXRhLCBwMj86IFQpID0+IFQgfCB1bmRlZmluZWQpIHwgbnVsbFxuICApIHtcbiAgICB0aGlzLmxvY2FsID0gbG9jYWwgfHwgc2VydmVyO1xuICAgIHRoaXMud3JpdGFibGUgPSAhIXdyaXRhYmxlO1xuICAgIHRoaXMueGZvcm0gPSB4Zm9ybSB8fCBub1hmb3JtXztcbiAgfVxufVxudHlwZSBNYXBwaW5ncyA9IEFycmF5PE1hcHBpbmc8c3RyaW5nPiB8IE1hcHBpbmc8bnVtYmVyPj47XG5cbmV4cG9ydCB7IE1hcHBpbmdzIH07XG5cbmxldCBtYXBwaW5nc186IE1hcHBpbmdzIHwgbnVsbCA9IG51bGw7XG5cbmV4cG9ydCBmdW5jdGlvbiB4Zm9ybVBhdGgoZnVsbFBhdGg6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghaXNTdHJpbmcoZnVsbFBhdGgpIHx8IGZ1bGxQYXRoLmxlbmd0aCA8IDIpIHtcbiAgICByZXR1cm4gZnVsbFBhdGg7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGxhc3RDb21wb25lbnQoZnVsbFBhdGgpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXBwaW5ncygpOiBNYXBwaW5ncyB7XG4gIGlmIChtYXBwaW5nc18pIHtcbiAgICByZXR1cm4gbWFwcGluZ3NfO1xuICB9XG4gIGNvbnN0IG1hcHBpbmdzOiBNYXBwaW5ncyA9IFtdO1xuICBtYXBwaW5ncy5wdXNoKG5ldyBNYXBwaW5nPHN0cmluZz4oJ2J1Y2tldCcpKTtcbiAgbWFwcGluZ3MucHVzaChuZXcgTWFwcGluZzxzdHJpbmc+KCdnZW5lcmF0aW9uJykpO1xuICBtYXBwaW5ncy5wdXNoKG5ldyBNYXBwaW5nPHN0cmluZz4oJ21ldGFnZW5lcmF0aW9uJykpO1xuICBtYXBwaW5ncy5wdXNoKG5ldyBNYXBwaW5nPHN0cmluZz4oJ25hbWUnLCAnZnVsbFBhdGgnLCB0cnVlKSk7XG5cbiAgZnVuY3Rpb24gbWFwcGluZ3NYZm9ybVBhdGgoXG4gICAgX21ldGFkYXRhOiBNZXRhZGF0YSxcbiAgICBmdWxsUGF0aDogc3RyaW5nIHwgdW5kZWZpbmVkXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHhmb3JtUGF0aChmdWxsUGF0aCk7XG4gIH1cbiAgY29uc3QgbmFtZU1hcHBpbmcgPSBuZXcgTWFwcGluZzxzdHJpbmc+KCduYW1lJyk7XG4gIG5hbWVNYXBwaW5nLnhmb3JtID0gbWFwcGluZ3NYZm9ybVBhdGg7XG4gIG1hcHBpbmdzLnB1c2gobmFtZU1hcHBpbmcpO1xuXG4gIC8qKlxuICAgKiBDb2VyY2VzIHRoZSBzZWNvbmQgcGFyYW0gdG8gYSBudW1iZXIsIGlmIGl0IGlzIGRlZmluZWQuXG4gICAqL1xuICBmdW5jdGlvbiB4Zm9ybVNpemUoXG4gICAgX21ldGFkYXRhOiBNZXRhZGF0YSxcbiAgICBzaXplPzogbnVtYmVyIHwgc3RyaW5nXG4gICk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIE51bWJlcihzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHNpemU7XG4gICAgfVxuICB9XG4gIGNvbnN0IHNpemVNYXBwaW5nID0gbmV3IE1hcHBpbmc8bnVtYmVyPignc2l6ZScpO1xuICBzaXplTWFwcGluZy54Zm9ybSA9IHhmb3JtU2l6ZTtcbiAgbWFwcGluZ3MucHVzaChzaXplTWFwcGluZyk7XG4gIG1hcHBpbmdzLnB1c2gobmV3IE1hcHBpbmc8bnVtYmVyPigndGltZUNyZWF0ZWQnKSk7XG4gIG1hcHBpbmdzLnB1c2gobmV3IE1hcHBpbmc8c3RyaW5nPigndXBkYXRlZCcpKTtcbiAgbWFwcGluZ3MucHVzaChuZXcgTWFwcGluZzxzdHJpbmc+KCdtZDVIYXNoJywgbnVsbCwgdHJ1ZSkpO1xuICBtYXBwaW5ncy5wdXNoKG5ldyBNYXBwaW5nPHN0cmluZz4oJ2NhY2hlQ29udHJvbCcsIG51bGwsIHRydWUpKTtcbiAgbWFwcGluZ3MucHVzaChuZXcgTWFwcGluZzxzdHJpbmc+KCdjb250ZW50RGlzcG9zaXRpb24nLCBudWxsLCB0cnVlKSk7XG4gIG1hcHBpbmdzLnB1c2gobmV3IE1hcHBpbmc8c3RyaW5nPignY29udGVudEVuY29kaW5nJywgbnVsbCwgdHJ1ZSkpO1xuICBtYXBwaW5ncy5wdXNoKG5ldyBNYXBwaW5nPHN0cmluZz4oJ2NvbnRlbnRMYW5ndWFnZScsIG51bGwsIHRydWUpKTtcbiAgbWFwcGluZ3MucHVzaChuZXcgTWFwcGluZzxzdHJpbmc+KCdjb250ZW50VHlwZScsIG51bGwsIHRydWUpKTtcbiAgbWFwcGluZ3MucHVzaChuZXcgTWFwcGluZzxzdHJpbmc+KCdtZXRhZGF0YScsICdjdXN0b21NZXRhZGF0YScsIHRydWUpKTtcbiAgbWFwcGluZ3NfID0gbWFwcGluZ3M7XG4gIHJldHVybiBtYXBwaW5nc187XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZGRSZWYobWV0YWRhdGE6IE1ldGFkYXRhLCBzZXJ2aWNlOiBGaXJlYmFzZVN0b3JhZ2VJbXBsKTogdm9pZCB7XG4gIGZ1bmN0aW9uIGdlbmVyYXRlUmVmKCk6IFJlZmVyZW5jZSB7XG4gICAgY29uc3QgYnVja2V0OiBzdHJpbmcgPSBtZXRhZGF0YVsnYnVja2V0J10gYXMgc3RyaW5nO1xuICAgIGNvbnN0IHBhdGg6IHN0cmluZyA9IG1ldGFkYXRhWydmdWxsUGF0aCddIGFzIHN0cmluZztcbiAgICBjb25zdCBsb2MgPSBuZXcgTG9jYXRpb24oYnVja2V0LCBwYXRoKTtcbiAgICByZXR1cm4gc2VydmljZS5fbWFrZVN0b3JhZ2VSZWZlcmVuY2UobG9jKTtcbiAgfVxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkobWV0YWRhdGEsICdyZWYnLCB7IGdldDogZ2VuZXJhdGVSZWYgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tUmVzb3VyY2UoXG4gIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIHJlc291cmNlOiB7IFtuYW1lOiBzdHJpbmddOiB1bmtub3duIH0sXG4gIG1hcHBpbmdzOiBNYXBwaW5nc1xuKTogTWV0YWRhdGEge1xuICBjb25zdCBtZXRhZGF0YTogTWV0YWRhdGEgPSB7fSBhcyBNZXRhZGF0YTtcbiAgbWV0YWRhdGFbJ3R5cGUnXSA9ICdmaWxlJztcbiAgY29uc3QgbGVuID0gbWFwcGluZ3MubGVuZ3RoO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgY29uc3QgbWFwcGluZyA9IG1hcHBpbmdzW2ldO1xuICAgIG1ldGFkYXRhW21hcHBpbmcubG9jYWxdID0gKG1hcHBpbmcgYXMgTWFwcGluZzx1bmtub3duPikueGZvcm0oXG4gICAgICBtZXRhZGF0YSxcbiAgICAgIHJlc291cmNlW21hcHBpbmcuc2VydmVyXVxuICAgICk7XG4gIH1cbiAgYWRkUmVmKG1ldGFkYXRhLCBzZXJ2aWNlKTtcbiAgcmV0dXJuIG1ldGFkYXRhO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJlc291cmNlU3RyaW5nKFxuICBzZXJ2aWNlOiBGaXJlYmFzZVN0b3JhZ2VJbXBsLFxuICByZXNvdXJjZVN0cmluZzogc3RyaW5nLFxuICBtYXBwaW5nczogTWFwcGluZ3Ncbik6IE1ldGFkYXRhIHwgbnVsbCB7XG4gIGNvbnN0IG9iaiA9IGpzb25PYmplY3RPck51bGwocmVzb3VyY2VTdHJpbmcpO1xuICBpZiAob2JqID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgcmVzb3VyY2UgPSBvYmogYXMgTWV0YWRhdGE7XG4gIHJldHVybiBmcm9tUmVzb3VyY2Uoc2VydmljZSwgcmVzb3VyY2UsIG1hcHBpbmdzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRvd25sb2FkVXJsRnJvbVJlc291cmNlU3RyaW5nKFxuICBtZXRhZGF0YTogTWV0YWRhdGEsXG4gIHJlc291cmNlU3RyaW5nOiBzdHJpbmcsXG4gIGhvc3Q6IHN0cmluZyxcbiAgcHJvdG9jb2w6IHN0cmluZ1xuKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IG9iaiA9IGpzb25PYmplY3RPck51bGwocmVzb3VyY2VTdHJpbmcpO1xuICBpZiAob2JqID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaWYgKCFpc1N0cmluZyhvYmpbJ2Rvd25sb2FkVG9rZW5zJ10pKSB7XG4gICAgLy8gVGhpcyBjYW4gaGFwcGVuIGlmIG9iamVjdHMgYXJlIHVwbG9hZGVkIHRocm91Z2ggR0NTIGFuZCByZXRyaWV2ZWRcbiAgICAvLyB0aHJvdWdoIGxpc3QsIHNvIHdlIGRvbid0IHdhbnQgdG8gdGhyb3cgYW4gRXJyb3IuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgdG9rZW5zOiBzdHJpbmcgPSBvYmpbJ2Rvd25sb2FkVG9rZW5zJ10gYXMgc3RyaW5nO1xuICBpZiAodG9rZW5zLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IGVuY29kZSA9IGVuY29kZVVSSUNvbXBvbmVudDtcbiAgY29uc3QgdG9rZW5zTGlzdCA9IHRva2Vucy5zcGxpdCgnLCcpO1xuICBjb25zdCB1cmxzID0gdG9rZW5zTGlzdC5tYXAoKHRva2VuOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgIGNvbnN0IGJ1Y2tldDogc3RyaW5nID0gbWV0YWRhdGFbJ2J1Y2tldCddIGFzIHN0cmluZztcbiAgICBjb25zdCBwYXRoOiBzdHJpbmcgPSBtZXRhZGF0YVsnZnVsbFBhdGgnXSBhcyBzdHJpbmc7XG4gICAgY29uc3QgdXJsUGFydCA9ICcvYi8nICsgZW5jb2RlKGJ1Y2tldCkgKyAnL28vJyArIGVuY29kZShwYXRoKTtcbiAgICBjb25zdCBiYXNlID0gbWFrZVVybCh1cmxQYXJ0LCBob3N0LCBwcm90b2NvbCk7XG4gICAgY29uc3QgcXVlcnlTdHJpbmcgPSBtYWtlUXVlcnlTdHJpbmcoe1xuICAgICAgYWx0OiAnbWVkaWEnLFxuICAgICAgdG9rZW5cbiAgICB9KTtcbiAgICByZXR1cm4gYmFzZSArIHF1ZXJ5U3RyaW5nO1xuICB9KTtcbiAgcmV0dXJuIHVybHNbMF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b1Jlc291cmNlU3RyaW5nKFxuICBtZXRhZGF0YTogUGFydGlhbDxNZXRhZGF0YT4sXG4gIG1hcHBpbmdzOiBNYXBwaW5nc1xuKTogc3RyaW5nIHtcbiAgY29uc3QgcmVzb3VyY2U6IHtcbiAgICBbcHJvcDogc3RyaW5nXTogdW5rbm93bjtcbiAgfSA9IHt9O1xuICBjb25zdCBsZW4gPSBtYXBwaW5ncy5sZW5ndGg7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICBjb25zdCBtYXBwaW5nID0gbWFwcGluZ3NbaV07XG4gICAgaWYgKG1hcHBpbmcud3JpdGFibGUpIHtcbiAgICAgIHJlc291cmNlW21hcHBpbmcuc2VydmVyXSA9IG1ldGFkYXRhW21hcHBpbmcubG9jYWxdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkocmVzb3VyY2UpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQGZpbGVvdmVydmlldyBEb2N1bWVudGF0aW9uIGZvciB0aGUgbGlzdE9wdGlvbnMgYW5kIGxpc3RSZXN1bHQgZm9ybWF0XG4gKi9cbmltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnLi9sb2NhdGlvbic7XG5pbXBvcnQgeyBqc29uT2JqZWN0T3JOdWxsIH0gZnJvbSAnLi9qc29uJztcbmltcG9ydCB7IExpc3RSZXN1bHQgfSBmcm9tICcuLi9saXN0JztcbmltcG9ydCB7IEZpcmViYXNlU3RvcmFnZUltcGwgfSBmcm9tICcuLi9zZXJ2aWNlJztcblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBzaW1wbGlmaWVkIG9iamVjdCBtZXRhZGF0YSByZXR1cm5lZCBieSBMaXN0IEFQSS5cbiAqIE90aGVyIGZpZWxkcyBhcmUgZmlsdGVyZWQgYmVjYXVzZSBsaXN0IGluIEZpcmViYXNlIFJ1bGVzIGRvZXMgbm90IGdyYW50XG4gKiB0aGUgcGVybWlzc2lvbiB0byByZWFkIHRoZSBtZXRhZGF0YS5cbiAqL1xuaW50ZXJmYWNlIExpc3RNZXRhZGF0YVJlc3BvbnNlIHtcbiAgbmFtZTogc3RyaW5nO1xuICBidWNrZXQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBKU09OIHJlc3BvbnNlIG9mIExpc3QgQVBJLlxuICovXG5pbnRlcmZhY2UgTGlzdFJlc3VsdFJlc3BvbnNlIHtcbiAgcHJlZml4ZXM6IHN0cmluZ1tdO1xuICBpdGVtczogTGlzdE1ldGFkYXRhUmVzcG9uc2VbXTtcbiAgbmV4dFBhZ2VUb2tlbj86IHN0cmluZztcbn1cblxuY29uc3QgUFJFRklYRVNfS0VZID0gJ3ByZWZpeGVzJztcbmNvbnN0IElURU1TX0tFWSA9ICdpdGVtcyc7XG5cbmZ1bmN0aW9uIGZyb21CYWNrZW5kUmVzcG9uc2UoXG4gIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIGJ1Y2tldDogc3RyaW5nLFxuICByZXNvdXJjZTogTGlzdFJlc3VsdFJlc3BvbnNlXG4pOiBMaXN0UmVzdWx0IHtcbiAgY29uc3QgbGlzdFJlc3VsdDogTGlzdFJlc3VsdCA9IHtcbiAgICBwcmVmaXhlczogW10sXG4gICAgaXRlbXM6IFtdLFxuICAgIG5leHRQYWdlVG9rZW46IHJlc291cmNlWyduZXh0UGFnZVRva2VuJ11cbiAgfTtcbiAgaWYgKHJlc291cmNlW1BSRUZJWEVTX0tFWV0pIHtcbiAgICBmb3IgKGNvbnN0IHBhdGggb2YgcmVzb3VyY2VbUFJFRklYRVNfS0VZXSkge1xuICAgICAgY29uc3QgcGF0aFdpdGhvdXRUcmFpbGluZ1NsYXNoID0gcGF0aC5yZXBsYWNlKC9cXC8kLywgJycpO1xuICAgICAgY29uc3QgcmVmZXJlbmNlID0gc2VydmljZS5fbWFrZVN0b3JhZ2VSZWZlcmVuY2UoXG4gICAgICAgIG5ldyBMb2NhdGlvbihidWNrZXQsIHBhdGhXaXRob3V0VHJhaWxpbmdTbGFzaClcbiAgICAgICk7XG4gICAgICBsaXN0UmVzdWx0LnByZWZpeGVzLnB1c2gocmVmZXJlbmNlKTtcbiAgICB9XG4gIH1cblxuICBpZiAocmVzb3VyY2VbSVRFTVNfS0VZXSkge1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiByZXNvdXJjZVtJVEVNU19LRVldKSB7XG4gICAgICBjb25zdCByZWZlcmVuY2UgPSBzZXJ2aWNlLl9tYWtlU3RvcmFnZVJlZmVyZW5jZShcbiAgICAgICAgbmV3IExvY2F0aW9uKGJ1Y2tldCwgaXRlbVsnbmFtZSddKVxuICAgICAgKTtcbiAgICAgIGxpc3RSZXN1bHQuaXRlbXMucHVzaChyZWZlcmVuY2UpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbGlzdFJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21SZXNwb25zZVN0cmluZyhcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgYnVja2V0OiBzdHJpbmcsXG4gIHJlc291cmNlU3RyaW5nOiBzdHJpbmdcbik6IExpc3RSZXN1bHQgfCBudWxsIHtcbiAgY29uc3Qgb2JqID0ganNvbk9iamVjdE9yTnVsbChyZXNvdXJjZVN0cmluZyk7XG4gIGlmIChvYmogPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCByZXNvdXJjZSA9IG9iaiBhcyB1bmtub3duIGFzIExpc3RSZXN1bHRSZXNwb25zZTtcbiAgcmV0dXJuIGZyb21CYWNrZW5kUmVzcG9uc2Uoc2VydmljZSwgYnVja2V0LCByZXNvdXJjZSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IFN0b3JhZ2VFcnJvciB9IGZyb20gJy4vZXJyb3InO1xuaW1wb3J0IHsgSGVhZGVycywgQ29ubmVjdGlvbiwgQ29ubmVjdGlvblR5cGUgfSBmcm9tICcuL2Nvbm5lY3Rpb24nO1xuXG4vKipcbiAqIFR5cGUgZm9yIHVybCBwYXJhbXMgc3RvcmVkIGluIFJlcXVlc3RJbmZvLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFVybFBhcmFtcyB7XG4gIFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXI7XG59XG5cbi8qKlxuICogQSBmdW5jdGlvbiB0aGF0IGNvbnZlcnRzIGEgc2VydmVyIHJlc3BvbnNlIHRvIHRoZSBBUEkgdHlwZSBleHBlY3RlZCBieSB0aGVcbiAqIFNESy5cbiAqXG4gKiBAcGFyYW0gSSAtIHRoZSB0eXBlIG9mIHRoZSBiYWNrZW5kJ3MgbmV0d29yayByZXNwb25zZVxuICogQHBhcmFtIE8gLSB0aGUgb3V0cHV0IHJlc3BvbnNlIHR5cGUgdXNlZCBieSB0aGUgcmVzdCBvZiB0aGUgU0RLLlxuICovXG5leHBvcnQgdHlwZSBSZXF1ZXN0SGFuZGxlcjxJIGV4dGVuZHMgQ29ubmVjdGlvblR5cGUsIE8+ID0gKFxuICBjb25uZWN0aW9uOiBDb25uZWN0aW9uPEk+LFxuICByZXNwb25zZTogSVxuKSA9PiBPO1xuXG4vKiogQSBmdW5jdGlvbiB0byBoYW5kbGUgYW4gZXJyb3IuICovXG5leHBvcnQgdHlwZSBFcnJvckhhbmRsZXIgPSAoXG4gIGNvbm5lY3Rpb246IENvbm5lY3Rpb248Q29ubmVjdGlvblR5cGU+LFxuICByZXNwb25zZTogU3RvcmFnZUVycm9yXG4pID0+IFN0b3JhZ2VFcnJvcjtcblxuLyoqXG4gKiBDb250YWlucyBhIGZ1bGx5IHNwZWNpZmllZCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSBJIC0gdGhlIHR5cGUgb2YgdGhlIGJhY2tlbmQncyBuZXR3b3JrIHJlc3BvbnNlLlxuICogQHBhcmFtIE8gLSB0aGUgb3V0cHV0IHJlc3BvbnNlIHR5cGUgdXNlZCBieSB0aGUgcmVzdCBvZiB0aGUgU0RLLlxuICovXG5leHBvcnQgY2xhc3MgUmVxdWVzdEluZm88SSBleHRlbmRzIENvbm5lY3Rpb25UeXBlLCBPPiB7XG4gIHVybFBhcmFtczogVXJsUGFyYW1zID0ge307XG4gIGhlYWRlcnM6IEhlYWRlcnMgPSB7fTtcbiAgYm9keTogQmxvYiB8IHN0cmluZyB8IFVpbnQ4QXJyYXkgfCBudWxsID0gbnVsbDtcbiAgZXJyb3JIYW5kbGVyOiBFcnJvckhhbmRsZXIgfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogQ2FsbGVkIHdpdGggdGhlIGN1cnJlbnQgbnVtYmVyIG9mIGJ5dGVzIHVwbG9hZGVkIGFuZCB0b3RhbCBzaXplICgtMSBpZiBub3RcbiAgICogY29tcHV0YWJsZSkgb2YgdGhlIHJlcXVlc3QgYm9keSAoaS5lLiB1c2VkIHRvIHJlcG9ydCB1cGxvYWQgcHJvZ3Jlc3MpLlxuICAgKi9cbiAgcHJvZ3Jlc3NDYWxsYmFjazogKChwMTogbnVtYmVyLCBwMjogbnVtYmVyKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuICBzdWNjZXNzQ29kZXM6IG51bWJlcltdID0gWzIwMF07XG4gIGFkZGl0aW9uYWxSZXRyeUNvZGVzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyB1cmw6IHN0cmluZyxcbiAgICBwdWJsaWMgbWV0aG9kOiBzdHJpbmcsXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdmFsdWUgd2l0aCB3aGljaCB0byByZXNvbHZlIHRoZSByZXF1ZXN0J3MgcHJvbWlzZS4gT25seSBjYWxsZWRcbiAgICAgKiBpZiB0aGUgcmVxdWVzdCBpcyBzdWNjZXNzZnVsLiBUaHJvdyBmcm9tIHRoaXMgZnVuY3Rpb24gdG8gcmVqZWN0IHRoZVxuICAgICAqIHJldHVybmVkIFJlcXVlc3QncyBwcm9taXNlIHdpdGggdGhlIHRocm93biBlcnJvci5cbiAgICAgKiBOb3RlOiBUaGUgWGhySW8gcGFzc2VkIHRvIHRoaXMgZnVuY3Rpb24gbWF5IGJlIHJldXNlZCBhZnRlciB0aGlzIGNhbGxiYWNrXG4gICAgICogcmV0dXJucy4gRG8gbm90IGtlZXAgYSByZWZlcmVuY2UgdG8gaXQgaW4gYW55IHdheS5cbiAgICAgKi9cbiAgICBwdWJsaWMgaGFuZGxlcjogUmVxdWVzdEhhbmRsZXI8SSwgTz4sXG4gICAgcHVibGljIHRpbWVvdXQ6IG51bWJlclxuICApIHt9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IERlZmluZXMgbWV0aG9kcyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgbmV0d29yay5cbiAqL1xuXG5pbXBvcnQgeyBNZXRhZGF0YSB9IGZyb20gJy4uL21ldGFkYXRhJztcbmltcG9ydCB7IExpc3RSZXN1bHQgfSBmcm9tICcuLi9saXN0JztcbmltcG9ydCB7IEZic0Jsb2IgfSBmcm9tICcuL2Jsb2InO1xuaW1wb3J0IHtcbiAgU3RvcmFnZUVycm9yLFxuICBjYW5ub3RTbGljZUJsb2IsXG4gIHVuYXV0aGVudGljYXRlZCxcbiAgcXVvdGFFeGNlZWRlZCxcbiAgdW5hdXRob3JpemVkLFxuICBvYmplY3ROb3RGb3VuZCxcbiAgc2VydmVyRmlsZVdyb25nU2l6ZSxcbiAgdW5rbm93bixcbiAgdW5hdXRob3JpemVkQXBwXG59IGZyb20gJy4vZXJyb3InO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICcuL2xvY2F0aW9uJztcbmltcG9ydCB7XG4gIE1hcHBpbmdzLFxuICBmcm9tUmVzb3VyY2VTdHJpbmcsXG4gIGRvd25sb2FkVXJsRnJvbVJlc291cmNlU3RyaW5nLFxuICB0b1Jlc291cmNlU3RyaW5nXG59IGZyb20gJy4vbWV0YWRhdGEnO1xuaW1wb3J0IHsgZnJvbVJlc3BvbnNlU3RyaW5nIH0gZnJvbSAnLi9saXN0JztcbmltcG9ydCB7IFJlcXVlc3RJbmZvLCBVcmxQYXJhbXMgfSBmcm9tICcuL3JlcXVlc3RpbmZvJztcbmltcG9ydCB7IGlzU3RyaW5nIH0gZnJvbSAnLi90eXBlJztcbmltcG9ydCB7IG1ha2VVcmwgfSBmcm9tICcuL3VybCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uLCBDb25uZWN0aW9uVHlwZSB9IGZyb20gJy4vY29ubmVjdGlvbic7XG5pbXBvcnQgeyBGaXJlYmFzZVN0b3JhZ2VJbXBsIH0gZnJvbSAnLi4vc2VydmljZSc7XG5cbi8qKlxuICogVGhyb3dzIHRoZSBVTktOT1dOIFN0b3JhZ2VFcnJvciBpZiBjbmRuIGlzIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlckNoZWNrKGNuZG46IGJvb2xlYW4pOiB2b2lkIHtcbiAgaWYgKCFjbmRuKSB7XG4gICAgdGhyb3cgdW5rbm93bigpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZXRhZGF0YUhhbmRsZXIoXG4gIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIG1hcHBpbmdzOiBNYXBwaW5nc1xuKTogKHAxOiBDb25uZWN0aW9uPHN0cmluZz4sIHAyOiBzdHJpbmcpID0+IE1ldGFkYXRhIHtcbiAgZnVuY3Rpb24gaGFuZGxlcih4aHI6IENvbm5lY3Rpb248c3RyaW5nPiwgdGV4dDogc3RyaW5nKTogTWV0YWRhdGEge1xuICAgIGNvbnN0IG1ldGFkYXRhID0gZnJvbVJlc291cmNlU3RyaW5nKHNlcnZpY2UsIHRleHQsIG1hcHBpbmdzKTtcbiAgICBoYW5kbGVyQ2hlY2sobWV0YWRhdGEgIT09IG51bGwpO1xuICAgIHJldHVybiBtZXRhZGF0YSBhcyBNZXRhZGF0YTtcbiAgfVxuICByZXR1cm4gaGFuZGxlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RIYW5kbGVyKFxuICBzZXJ2aWNlOiBGaXJlYmFzZVN0b3JhZ2VJbXBsLFxuICBidWNrZXQ6IHN0cmluZ1xuKTogKHAxOiBDb25uZWN0aW9uPHN0cmluZz4sIHAyOiBzdHJpbmcpID0+IExpc3RSZXN1bHQge1xuICBmdW5jdGlvbiBoYW5kbGVyKHhocjogQ29ubmVjdGlvbjxzdHJpbmc+LCB0ZXh0OiBzdHJpbmcpOiBMaXN0UmVzdWx0IHtcbiAgICBjb25zdCBsaXN0UmVzdWx0ID0gZnJvbVJlc3BvbnNlU3RyaW5nKHNlcnZpY2UsIGJ1Y2tldCwgdGV4dCk7XG4gICAgaGFuZGxlckNoZWNrKGxpc3RSZXN1bHQgIT09IG51bGwpO1xuICAgIHJldHVybiBsaXN0UmVzdWx0IGFzIExpc3RSZXN1bHQ7XG4gIH1cbiAgcmV0dXJuIGhhbmRsZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkb3dubG9hZFVybEhhbmRsZXIoXG4gIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIG1hcHBpbmdzOiBNYXBwaW5nc1xuKTogKHAxOiBDb25uZWN0aW9uPHN0cmluZz4sIHAyOiBzdHJpbmcpID0+IHN0cmluZyB8IG51bGwge1xuICBmdW5jdGlvbiBoYW5kbGVyKHhocjogQ29ubmVjdGlvbjxzdHJpbmc+LCB0ZXh0OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBtZXRhZGF0YSA9IGZyb21SZXNvdXJjZVN0cmluZyhzZXJ2aWNlLCB0ZXh0LCBtYXBwaW5ncyk7XG4gICAgaGFuZGxlckNoZWNrKG1ldGFkYXRhICE9PSBudWxsKTtcbiAgICByZXR1cm4gZG93bmxvYWRVcmxGcm9tUmVzb3VyY2VTdHJpbmcoXG4gICAgICBtZXRhZGF0YSBhcyBNZXRhZGF0YSxcbiAgICAgIHRleHQsXG4gICAgICBzZXJ2aWNlLmhvc3QsXG4gICAgICBzZXJ2aWNlLl9wcm90b2NvbFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIGhhbmRsZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaGFyZWRFcnJvckhhbmRsZXIoXG4gIGxvY2F0aW9uOiBMb2NhdGlvblxuKTogKHAxOiBDb25uZWN0aW9uPENvbm5lY3Rpb25UeXBlPiwgcDI6IFN0b3JhZ2VFcnJvcikgPT4gU3RvcmFnZUVycm9yIHtcbiAgZnVuY3Rpb24gZXJyb3JIYW5kbGVyKFxuICAgIHhocjogQ29ubmVjdGlvbjxDb25uZWN0aW9uVHlwZT4sXG4gICAgZXJyOiBTdG9yYWdlRXJyb3JcbiAgKTogU3RvcmFnZUVycm9yIHtcbiAgICBsZXQgbmV3RXJyOiBTdG9yYWdlRXJyb3I7XG4gICAgaWYgKHhoci5nZXRTdGF0dXMoKSA9PT0gNDAxKSB7XG4gICAgICBpZiAoXG4gICAgICAgIC8vIFRoaXMgZXhhY3QgbWVzc2FnZSBzdHJpbmcgaXMgdGhlIG9ubHkgY29uc2lzdGVudCBwYXJ0IG9mIHRoZVxuICAgICAgICAvLyBzZXJ2ZXIncyBlcnJvciByZXNwb25zZSB0aGF0IGlkZW50aWZpZXMgaXQgYXMgYW4gQXBwIENoZWNrIGVycm9yLlxuICAgICAgICB4aHIuZ2V0RXJyb3JUZXh0KCkuaW5jbHVkZXMoJ0ZpcmViYXNlIEFwcCBDaGVjayB0b2tlbiBpcyBpbnZhbGlkJylcbiAgICAgICkge1xuICAgICAgICBuZXdFcnIgPSB1bmF1dGhvcml6ZWRBcHAoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld0VyciA9IHVuYXV0aGVudGljYXRlZCgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoeGhyLmdldFN0YXR1cygpID09PSA0MDIpIHtcbiAgICAgICAgbmV3RXJyID0gcXVvdGFFeGNlZWRlZChsb2NhdGlvbi5idWNrZXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHhoci5nZXRTdGF0dXMoKSA9PT0gNDAzKSB7XG4gICAgICAgICAgbmV3RXJyID0gdW5hdXRob3JpemVkKGxvY2F0aW9uLnBhdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5ld0VyciA9IGVycjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBuZXdFcnIuc3RhdHVzID0geGhyLmdldFN0YXR1cygpO1xuICAgIG5ld0Vyci5zZXJ2ZXJSZXNwb25zZSA9IGVyci5zZXJ2ZXJSZXNwb25zZTtcbiAgICByZXR1cm4gbmV3RXJyO1xuICB9XG4gIHJldHVybiBlcnJvckhhbmRsZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvYmplY3RFcnJvckhhbmRsZXIoXG4gIGxvY2F0aW9uOiBMb2NhdGlvblxuKTogKHAxOiBDb25uZWN0aW9uPENvbm5lY3Rpb25UeXBlPiwgcDI6IFN0b3JhZ2VFcnJvcikgPT4gU3RvcmFnZUVycm9yIHtcbiAgY29uc3Qgc2hhcmVkID0gc2hhcmVkRXJyb3JIYW5kbGVyKGxvY2F0aW9uKTtcblxuICBmdW5jdGlvbiBlcnJvckhhbmRsZXIoXG4gICAgeGhyOiBDb25uZWN0aW9uPENvbm5lY3Rpb25UeXBlPixcbiAgICBlcnI6IFN0b3JhZ2VFcnJvclxuICApOiBTdG9yYWdlRXJyb3Ige1xuICAgIGxldCBuZXdFcnIgPSBzaGFyZWQoeGhyLCBlcnIpO1xuICAgIGlmICh4aHIuZ2V0U3RhdHVzKCkgPT09IDQwNCkge1xuICAgICAgbmV3RXJyID0gb2JqZWN0Tm90Rm91bmQobG9jYXRpb24ucGF0aCk7XG4gICAgfVxuICAgIG5ld0Vyci5zZXJ2ZXJSZXNwb25zZSA9IGVyci5zZXJ2ZXJSZXNwb25zZTtcbiAgICByZXR1cm4gbmV3RXJyO1xuICB9XG4gIHJldHVybiBlcnJvckhhbmRsZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRNZXRhZGF0YShcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICBtYXBwaW5nczogTWFwcGluZ3Ncbik6IFJlcXVlc3RJbmZvPHN0cmluZywgTWV0YWRhdGE+IHtcbiAgY29uc3QgdXJsUGFydCA9IGxvY2F0aW9uLmZ1bGxTZXJ2ZXJVcmwoKTtcbiAgY29uc3QgdXJsID0gbWFrZVVybCh1cmxQYXJ0LCBzZXJ2aWNlLmhvc3QsIHNlcnZpY2UuX3Byb3RvY29sKTtcbiAgY29uc3QgbWV0aG9kID0gJ0dFVCc7XG4gIGNvbnN0IHRpbWVvdXQgPSBzZXJ2aWNlLm1heE9wZXJhdGlvblJldHJ5VGltZTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSBuZXcgUmVxdWVzdEluZm8oXG4gICAgdXJsLFxuICAgIG1ldGhvZCxcbiAgICBtZXRhZGF0YUhhbmRsZXIoc2VydmljZSwgbWFwcGluZ3MpLFxuICAgIHRpbWVvdXRcbiAgKTtcbiAgcmVxdWVzdEluZm8uZXJyb3JIYW5kbGVyID0gb2JqZWN0RXJyb3JIYW5kbGVyKGxvY2F0aW9uKTtcbiAgcmV0dXJuIHJlcXVlc3RJbmZvO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbGlzdChcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICBkZWxpbWl0ZXI/OiBzdHJpbmcsXG4gIHBhZ2VUb2tlbj86IHN0cmluZyB8IG51bGwsXG4gIG1heFJlc3VsdHM/OiBudW1iZXIgfCBudWxsXG4pOiBSZXF1ZXN0SW5mbzxzdHJpbmcsIExpc3RSZXN1bHQ+IHtcbiAgY29uc3QgdXJsUGFyYW1zOiBVcmxQYXJhbXMgPSB7fTtcbiAgaWYgKGxvY2F0aW9uLmlzUm9vdCkge1xuICAgIHVybFBhcmFtc1sncHJlZml4J10gPSAnJztcbiAgfSBlbHNlIHtcbiAgICB1cmxQYXJhbXNbJ3ByZWZpeCddID0gbG9jYXRpb24ucGF0aCArICcvJztcbiAgfVxuICBpZiAoZGVsaW1pdGVyICYmIGRlbGltaXRlci5sZW5ndGggPiAwKSB7XG4gICAgdXJsUGFyYW1zWydkZWxpbWl0ZXInXSA9IGRlbGltaXRlcjtcbiAgfVxuICBpZiAocGFnZVRva2VuKSB7XG4gICAgdXJsUGFyYW1zWydwYWdlVG9rZW4nXSA9IHBhZ2VUb2tlbjtcbiAgfVxuICBpZiAobWF4UmVzdWx0cykge1xuICAgIHVybFBhcmFtc1snbWF4UmVzdWx0cyddID0gbWF4UmVzdWx0cztcbiAgfVxuICBjb25zdCB1cmxQYXJ0ID0gbG9jYXRpb24uYnVja2V0T25seVNlcnZlclVybCgpO1xuICBjb25zdCB1cmwgPSBtYWtlVXJsKHVybFBhcnQsIHNlcnZpY2UuaG9zdCwgc2VydmljZS5fcHJvdG9jb2wpO1xuICBjb25zdCBtZXRob2QgPSAnR0VUJztcbiAgY29uc3QgdGltZW91dCA9IHNlcnZpY2UubWF4T3BlcmF0aW9uUmV0cnlUaW1lO1xuICBjb25zdCByZXF1ZXN0SW5mbyA9IG5ldyBSZXF1ZXN0SW5mbyhcbiAgICB1cmwsXG4gICAgbWV0aG9kLFxuICAgIGxpc3RIYW5kbGVyKHNlcnZpY2UsIGxvY2F0aW9uLmJ1Y2tldCksXG4gICAgdGltZW91dFxuICApO1xuICByZXF1ZXN0SW5mby51cmxQYXJhbXMgPSB1cmxQYXJhbXM7XG4gIHJlcXVlc3RJbmZvLmVycm9ySGFuZGxlciA9IHNoYXJlZEVycm9ySGFuZGxlcihsb2NhdGlvbik7XG4gIHJldHVybiByZXF1ZXN0SW5mbztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJ5dGVzPEkgZXh0ZW5kcyBDb25uZWN0aW9uVHlwZT4oXG4gIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIGxvY2F0aW9uOiBMb2NhdGlvbixcbiAgbWF4RG93bmxvYWRTaXplQnl0ZXM/OiBudW1iZXJcbik6IFJlcXVlc3RJbmZvPEksIEk+IHtcbiAgY29uc3QgdXJsUGFydCA9IGxvY2F0aW9uLmZ1bGxTZXJ2ZXJVcmwoKTtcbiAgY29uc3QgdXJsID0gbWFrZVVybCh1cmxQYXJ0LCBzZXJ2aWNlLmhvc3QsIHNlcnZpY2UuX3Byb3RvY29sKSArICc/YWx0PW1lZGlhJztcbiAgY29uc3QgbWV0aG9kID0gJ0dFVCc7XG4gIGNvbnN0IHRpbWVvdXQgPSBzZXJ2aWNlLm1heE9wZXJhdGlvblJldHJ5VGltZTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSBuZXcgUmVxdWVzdEluZm8oXG4gICAgdXJsLFxuICAgIG1ldGhvZCxcbiAgICAoXzogQ29ubmVjdGlvbjxJPiwgZGF0YTogSSkgPT4gZGF0YSxcbiAgICB0aW1lb3V0XG4gICk7XG4gIHJlcXVlc3RJbmZvLmVycm9ySGFuZGxlciA9IG9iamVjdEVycm9ySGFuZGxlcihsb2NhdGlvbik7XG4gIGlmIChtYXhEb3dubG9hZFNpemVCeXRlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmVxdWVzdEluZm8uaGVhZGVyc1snUmFuZ2UnXSA9IGBieXRlcz0wLSR7bWF4RG93bmxvYWRTaXplQnl0ZXN9YDtcbiAgICByZXF1ZXN0SW5mby5zdWNjZXNzQ29kZXMgPSBbMjAwIC8qIE9LICovLCAyMDYgLyogUGFydGlhbCBDb250ZW50ICovXTtcbiAgfVxuICByZXR1cm4gcmVxdWVzdEluZm87XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREb3dubG9hZFVybChcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICBtYXBwaW5nczogTWFwcGluZ3Ncbik6IFJlcXVlc3RJbmZvPHN0cmluZywgc3RyaW5nIHwgbnVsbD4ge1xuICBjb25zdCB1cmxQYXJ0ID0gbG9jYXRpb24uZnVsbFNlcnZlclVybCgpO1xuICBjb25zdCB1cmwgPSBtYWtlVXJsKHVybFBhcnQsIHNlcnZpY2UuaG9zdCwgc2VydmljZS5fcHJvdG9jb2wpO1xuICBjb25zdCBtZXRob2QgPSAnR0VUJztcbiAgY29uc3QgdGltZW91dCA9IHNlcnZpY2UubWF4T3BlcmF0aW9uUmV0cnlUaW1lO1xuICBjb25zdCByZXF1ZXN0SW5mbyA9IG5ldyBSZXF1ZXN0SW5mbyhcbiAgICB1cmwsXG4gICAgbWV0aG9kLFxuICAgIGRvd25sb2FkVXJsSGFuZGxlcihzZXJ2aWNlLCBtYXBwaW5ncyksXG4gICAgdGltZW91dFxuICApO1xuICByZXF1ZXN0SW5mby5lcnJvckhhbmRsZXIgPSBvYmplY3RFcnJvckhhbmRsZXIobG9jYXRpb24pO1xuICByZXR1cm4gcmVxdWVzdEluZm87XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVNZXRhZGF0YShcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICBtZXRhZGF0YTogUGFydGlhbDxNZXRhZGF0YT4sXG4gIG1hcHBpbmdzOiBNYXBwaW5nc1xuKTogUmVxdWVzdEluZm88c3RyaW5nLCBNZXRhZGF0YT4ge1xuICBjb25zdCB1cmxQYXJ0ID0gbG9jYXRpb24uZnVsbFNlcnZlclVybCgpO1xuICBjb25zdCB1cmwgPSBtYWtlVXJsKHVybFBhcnQsIHNlcnZpY2UuaG9zdCwgc2VydmljZS5fcHJvdG9jb2wpO1xuICBjb25zdCBtZXRob2QgPSAnUEFUQ0gnO1xuICBjb25zdCBib2R5ID0gdG9SZXNvdXJjZVN0cmluZyhtZXRhZGF0YSwgbWFwcGluZ3MpO1xuICBjb25zdCBoZWFkZXJzID0geyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnIH07XG4gIGNvbnN0IHRpbWVvdXQgPSBzZXJ2aWNlLm1heE9wZXJhdGlvblJldHJ5VGltZTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSBuZXcgUmVxdWVzdEluZm8oXG4gICAgdXJsLFxuICAgIG1ldGhvZCxcbiAgICBtZXRhZGF0YUhhbmRsZXIoc2VydmljZSwgbWFwcGluZ3MpLFxuICAgIHRpbWVvdXRcbiAgKTtcbiAgcmVxdWVzdEluZm8uaGVhZGVycyA9IGhlYWRlcnM7XG4gIHJlcXVlc3RJbmZvLmJvZHkgPSBib2R5O1xuICByZXF1ZXN0SW5mby5lcnJvckhhbmRsZXIgPSBvYmplY3RFcnJvckhhbmRsZXIobG9jYXRpb24pO1xuICByZXR1cm4gcmVxdWVzdEluZm87XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWxldGVPYmplY3QoXG4gIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIGxvY2F0aW9uOiBMb2NhdGlvblxuKTogUmVxdWVzdEluZm88c3RyaW5nLCB2b2lkPiB7XG4gIGNvbnN0IHVybFBhcnQgPSBsb2NhdGlvbi5mdWxsU2VydmVyVXJsKCk7XG4gIGNvbnN0IHVybCA9IG1ha2VVcmwodXJsUGFydCwgc2VydmljZS5ob3N0LCBzZXJ2aWNlLl9wcm90b2NvbCk7XG4gIGNvbnN0IG1ldGhvZCA9ICdERUxFVEUnO1xuICBjb25zdCB0aW1lb3V0ID0gc2VydmljZS5tYXhPcGVyYXRpb25SZXRyeVRpbWU7XG5cbiAgZnVuY3Rpb24gaGFuZGxlcihfeGhyOiBDb25uZWN0aW9uPHN0cmluZz4sIF90ZXh0OiBzdHJpbmcpOiB2b2lkIHt9XG4gIGNvbnN0IHJlcXVlc3RJbmZvID0gbmV3IFJlcXVlc3RJbmZvKHVybCwgbWV0aG9kLCBoYW5kbGVyLCB0aW1lb3V0KTtcbiAgcmVxdWVzdEluZm8uc3VjY2Vzc0NvZGVzID0gWzIwMCwgMjA0XTtcbiAgcmVxdWVzdEluZm8uZXJyb3JIYW5kbGVyID0gb2JqZWN0RXJyb3JIYW5kbGVyKGxvY2F0aW9uKTtcbiAgcmV0dXJuIHJlcXVlc3RJbmZvO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGV0ZXJtaW5lQ29udGVudFR5cGVfKFxuICBtZXRhZGF0YTogTWV0YWRhdGEgfCBudWxsLFxuICBibG9iOiBGYnNCbG9iIHwgbnVsbFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIChcbiAgICAobWV0YWRhdGEgJiYgbWV0YWRhdGFbJ2NvbnRlbnRUeXBlJ10pIHx8XG4gICAgKGJsb2IgJiYgYmxvYi50eXBlKCkpIHx8XG4gICAgJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSdcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ldGFkYXRhRm9yVXBsb2FkXyhcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICBibG9iOiBGYnNCbG9iLFxuICBtZXRhZGF0YT86IE1ldGFkYXRhIHwgbnVsbFxuKTogTWV0YWRhdGEge1xuICBjb25zdCBtZXRhZGF0YUNsb25lID0gT2JqZWN0LmFzc2lnbih7fSwgbWV0YWRhdGEpO1xuICBtZXRhZGF0YUNsb25lWydmdWxsUGF0aCddID0gbG9jYXRpb24ucGF0aDtcbiAgbWV0YWRhdGFDbG9uZVsnc2l6ZSddID0gYmxvYi5zaXplKCk7XG4gIGlmICghbWV0YWRhdGFDbG9uZVsnY29udGVudFR5cGUnXSkge1xuICAgIG1ldGFkYXRhQ2xvbmVbJ2NvbnRlbnRUeXBlJ10gPSBkZXRlcm1pbmVDb250ZW50VHlwZV8obnVsbCwgYmxvYik7XG4gIH1cbiAgcmV0dXJuIG1ldGFkYXRhQ2xvbmU7XG59XG5cbi8qKlxuICogUHJlcGFyZSBSZXF1ZXN0SW5mbyBmb3IgdXBsb2FkcyBhcyBDb250ZW50LVR5cGU6IG11bHRpcGFydC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG11bHRpcGFydFVwbG9hZChcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICBtYXBwaW5nczogTWFwcGluZ3MsXG4gIGJsb2I6IEZic0Jsb2IsXG4gIG1ldGFkYXRhPzogTWV0YWRhdGEgfCBudWxsXG4pOiBSZXF1ZXN0SW5mbzxzdHJpbmcsIE1ldGFkYXRhPiB7XG4gIGNvbnN0IHVybFBhcnQgPSBsb2NhdGlvbi5idWNrZXRPbmx5U2VydmVyVXJsKCk7XG4gIGNvbnN0IGhlYWRlcnM6IHsgW3Byb3A6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICdYLUdvb2ctVXBsb2FkLVByb3RvY29sJzogJ211bHRpcGFydCdcbiAgfTtcblxuICBmdW5jdGlvbiBnZW5Cb3VuZGFyeSgpOiBzdHJpbmcge1xuICAgIGxldCBzdHIgPSAnJztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgc3RyID0gc3RyICsgTWF0aC5yYW5kb20oKS50b1N0cmluZygpLnNsaWNlKDIpO1xuICAgIH1cbiAgICByZXR1cm4gc3RyO1xuICB9XG4gIGNvbnN0IGJvdW5kYXJ5ID0gZ2VuQm91bmRhcnkoKTtcbiAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gPSAnbXVsdGlwYXJ0L3JlbGF0ZWQ7IGJvdW5kYXJ5PScgKyBib3VuZGFyeTtcbiAgY29uc3QgbWV0YWRhdGFfID0gbWV0YWRhdGFGb3JVcGxvYWRfKGxvY2F0aW9uLCBibG9iLCBtZXRhZGF0YSk7XG4gIGNvbnN0IG1ldGFkYXRhU3RyaW5nID0gdG9SZXNvdXJjZVN0cmluZyhtZXRhZGF0YV8sIG1hcHBpbmdzKTtcbiAgY29uc3QgcHJlQmxvYlBhcnQgPVxuICAgICctLScgK1xuICAgIGJvdW5kYXJ5ICtcbiAgICAnXFxyXFxuJyArXG4gICAgJ0NvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOFxcclxcblxcclxcbicgK1xuICAgIG1ldGFkYXRhU3RyaW5nICtcbiAgICAnXFxyXFxuLS0nICtcbiAgICBib3VuZGFyeSArXG4gICAgJ1xcclxcbicgK1xuICAgICdDb250ZW50LVR5cGU6ICcgK1xuICAgIG1ldGFkYXRhX1snY29udGVudFR5cGUnXSArXG4gICAgJ1xcclxcblxcclxcbic7XG4gIGNvbnN0IHBvc3RCbG9iUGFydCA9ICdcXHJcXG4tLScgKyBib3VuZGFyeSArICctLSc7XG4gIGNvbnN0IGJvZHkgPSBGYnNCbG9iLmdldEJsb2IocHJlQmxvYlBhcnQsIGJsb2IsIHBvc3RCbG9iUGFydCk7XG4gIGlmIChib2R5ID09PSBudWxsKSB7XG4gICAgdGhyb3cgY2Fubm90U2xpY2VCbG9iKCk7XG4gIH1cbiAgY29uc3QgdXJsUGFyYW1zOiBVcmxQYXJhbXMgPSB7IG5hbWU6IG1ldGFkYXRhX1snZnVsbFBhdGgnXSEgfTtcbiAgY29uc3QgdXJsID0gbWFrZVVybCh1cmxQYXJ0LCBzZXJ2aWNlLmhvc3QsIHNlcnZpY2UuX3Byb3RvY29sKTtcbiAgY29uc3QgbWV0aG9kID0gJ1BPU1QnO1xuICBjb25zdCB0aW1lb3V0ID0gc2VydmljZS5tYXhVcGxvYWRSZXRyeVRpbWU7XG4gIGNvbnN0IHJlcXVlc3RJbmZvID0gbmV3IFJlcXVlc3RJbmZvKFxuICAgIHVybCxcbiAgICBtZXRob2QsXG4gICAgbWV0YWRhdGFIYW5kbGVyKHNlcnZpY2UsIG1hcHBpbmdzKSxcbiAgICB0aW1lb3V0XG4gICk7XG4gIHJlcXVlc3RJbmZvLnVybFBhcmFtcyA9IHVybFBhcmFtcztcbiAgcmVxdWVzdEluZm8uaGVhZGVycyA9IGhlYWRlcnM7XG4gIHJlcXVlc3RJbmZvLmJvZHkgPSBib2R5LnVwbG9hZERhdGEoKTtcbiAgcmVxdWVzdEluZm8uZXJyb3JIYW5kbGVyID0gc2hhcmVkRXJyb3JIYW5kbGVyKGxvY2F0aW9uKTtcbiAgcmV0dXJuIHJlcXVlc3RJbmZvO1xufVxuXG4vKipcbiAqIEBwYXJhbSBjdXJyZW50IFRoZSBudW1iZXIgb2YgYnl0ZXMgdGhhdCBoYXZlIGJlZW4gdXBsb2FkZWQgc28gZmFyLlxuICogQHBhcmFtIHRvdGFsIFRoZSB0b3RhbCBudW1iZXIgb2YgYnl0ZXMgaW4gdGhlIHVwbG9hZC5cbiAqIEBwYXJhbSBvcHRfZmluYWxpemVkIFRydWUgaWYgdGhlIHNlcnZlciBoYXMgZmluaXNoZWQgdGhlIHVwbG9hZC5cbiAqIEBwYXJhbSBvcHRfbWV0YWRhdGEgVGhlIHVwbG9hZCBtZXRhZGF0YSwgc2hvdWxkXG4gKiAgICAgb25seSBiZSBwYXNzZWQgaWYgb3B0X2ZpbmFsaXplZCBpcyB0cnVlLlxuICovXG5leHBvcnQgY2xhc3MgUmVzdW1hYmxlVXBsb2FkU3RhdHVzIHtcbiAgZmluYWxpemVkOiBib29sZWFuO1xuICBtZXRhZGF0YTogTWV0YWRhdGEgfCBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBjdXJyZW50OiBudW1iZXIsXG4gICAgcHVibGljIHRvdGFsOiBudW1iZXIsXG4gICAgZmluYWxpemVkPzogYm9vbGVhbixcbiAgICBtZXRhZGF0YT86IE1ldGFkYXRhIHwgbnVsbFxuICApIHtcbiAgICB0aGlzLmZpbmFsaXplZCA9ICEhZmluYWxpemVkO1xuICAgIHRoaXMubWV0YWRhdGEgPSBtZXRhZGF0YSB8fCBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGVja1Jlc3VtZUhlYWRlcl8oXG4gIHhocjogQ29ubmVjdGlvbjxzdHJpbmc+LFxuICBhbGxvd2VkPzogc3RyaW5nW11cbik6IHN0cmluZyB7XG4gIGxldCBzdGF0dXM6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICB0cnkge1xuICAgIHN0YXR1cyA9IHhoci5nZXRSZXNwb25zZUhlYWRlcignWC1Hb29nLVVwbG9hZC1TdGF0dXMnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGhhbmRsZXJDaGVjayhmYWxzZSk7XG4gIH1cbiAgY29uc3QgYWxsb3dlZFN0YXR1cyA9IGFsbG93ZWQgfHwgWydhY3RpdmUnXTtcbiAgaGFuZGxlckNoZWNrKCEhc3RhdHVzICYmIGFsbG93ZWRTdGF0dXMuaW5kZXhPZihzdGF0dXMpICE9PSAtMSk7XG4gIHJldHVybiBzdGF0dXMgYXMgc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVzdW1hYmxlVXBsb2FkKFxuICBzZXJ2aWNlOiBGaXJlYmFzZVN0b3JhZ2VJbXBsLFxuICBsb2NhdGlvbjogTG9jYXRpb24sXG4gIG1hcHBpbmdzOiBNYXBwaW5ncyxcbiAgYmxvYjogRmJzQmxvYixcbiAgbWV0YWRhdGE/OiBNZXRhZGF0YSB8IG51bGxcbik6IFJlcXVlc3RJbmZvPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IHVybFBhcnQgPSBsb2NhdGlvbi5idWNrZXRPbmx5U2VydmVyVXJsKCk7XG4gIGNvbnN0IG1ldGFkYXRhRm9yVXBsb2FkID0gbWV0YWRhdGFGb3JVcGxvYWRfKGxvY2F0aW9uLCBibG9iLCBtZXRhZGF0YSk7XG4gIGNvbnN0IHVybFBhcmFtczogVXJsUGFyYW1zID0geyBuYW1lOiBtZXRhZGF0YUZvclVwbG9hZFsnZnVsbFBhdGgnXSEgfTtcbiAgY29uc3QgdXJsID0gbWFrZVVybCh1cmxQYXJ0LCBzZXJ2aWNlLmhvc3QsIHNlcnZpY2UuX3Byb3RvY29sKTtcbiAgY29uc3QgbWV0aG9kID0gJ1BPU1QnO1xuICBjb25zdCBoZWFkZXJzID0ge1xuICAgICdYLUdvb2ctVXBsb2FkLVByb3RvY29sJzogJ3Jlc3VtYWJsZScsXG4gICAgJ1gtR29vZy1VcGxvYWQtQ29tbWFuZCc6ICdzdGFydCcsXG4gICAgJ1gtR29vZy1VcGxvYWQtSGVhZGVyLUNvbnRlbnQtTGVuZ3RoJzogYCR7YmxvYi5zaXplKCl9YCxcbiAgICAnWC1Hb29nLVVwbG9hZC1IZWFkZXItQ29udGVudC1UeXBlJzogbWV0YWRhdGFGb3JVcGxvYWRbJ2NvbnRlbnRUeXBlJ10hLFxuICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOCdcbiAgfTtcbiAgY29uc3QgYm9keSA9IHRvUmVzb3VyY2VTdHJpbmcobWV0YWRhdGFGb3JVcGxvYWQsIG1hcHBpbmdzKTtcbiAgY29uc3QgdGltZW91dCA9IHNlcnZpY2UubWF4VXBsb2FkUmV0cnlUaW1lO1xuXG4gIGZ1bmN0aW9uIGhhbmRsZXIoeGhyOiBDb25uZWN0aW9uPHN0cmluZz4pOiBzdHJpbmcge1xuICAgIGNoZWNrUmVzdW1lSGVhZGVyXyh4aHIpO1xuICAgIGxldCB1cmw7XG4gICAgdHJ5IHtcbiAgICAgIHVybCA9IHhoci5nZXRSZXNwb25zZUhlYWRlcignWC1Hb29nLVVwbG9hZC1VUkwnKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBoYW5kbGVyQ2hlY2soZmFsc2UpO1xuICAgIH1cbiAgICBoYW5kbGVyQ2hlY2soaXNTdHJpbmcodXJsKSk7XG4gICAgcmV0dXJuIHVybCBhcyBzdHJpbmc7XG4gIH1cbiAgY29uc3QgcmVxdWVzdEluZm8gPSBuZXcgUmVxdWVzdEluZm8odXJsLCBtZXRob2QsIGhhbmRsZXIsIHRpbWVvdXQpO1xuICByZXF1ZXN0SW5mby51cmxQYXJhbXMgPSB1cmxQYXJhbXM7XG4gIHJlcXVlc3RJbmZvLmhlYWRlcnMgPSBoZWFkZXJzO1xuICByZXF1ZXN0SW5mby5ib2R5ID0gYm9keTtcbiAgcmVxdWVzdEluZm8uZXJyb3JIYW5kbGVyID0gc2hhcmVkRXJyb3JIYW5kbGVyKGxvY2F0aW9uKTtcbiAgcmV0dXJuIHJlcXVlc3RJbmZvO1xufVxuXG4vKipcbiAqIEBwYXJhbSB1cmwgRnJvbSBhIGNhbGwgdG8gZmJzLnJlcXVlc3RzLmNyZWF0ZVJlc3VtYWJsZVVwbG9hZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJlc3VtYWJsZVVwbG9hZFN0YXR1cyhcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgbG9jYXRpb246IExvY2F0aW9uLFxuICB1cmw6IHN0cmluZyxcbiAgYmxvYjogRmJzQmxvYlxuKTogUmVxdWVzdEluZm88c3RyaW5nLCBSZXN1bWFibGVVcGxvYWRTdGF0dXM+IHtcbiAgY29uc3QgaGVhZGVycyA9IHsgJ1gtR29vZy1VcGxvYWQtQ29tbWFuZCc6ICdxdWVyeScgfTtcblxuICBmdW5jdGlvbiBoYW5kbGVyKHhocjogQ29ubmVjdGlvbjxzdHJpbmc+KTogUmVzdW1hYmxlVXBsb2FkU3RhdHVzIHtcbiAgICBjb25zdCBzdGF0dXMgPSBjaGVja1Jlc3VtZUhlYWRlcl8oeGhyLCBbJ2FjdGl2ZScsICdmaW5hbCddKTtcbiAgICBsZXQgc2l6ZVN0cmluZzogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIHNpemVTdHJpbmcgPSB4aHIuZ2V0UmVzcG9uc2VIZWFkZXIoJ1gtR29vZy1VcGxvYWQtU2l6ZS1SZWNlaXZlZCcpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGhhbmRsZXJDaGVjayhmYWxzZSk7XG4gICAgfVxuXG4gICAgaWYgKCFzaXplU3RyaW5nKSB7XG4gICAgICAvLyBudWxsIG9yIGVtcHR5IHN0cmluZ1xuICAgICAgaGFuZGxlckNoZWNrKGZhbHNlKTtcbiAgICB9XG5cbiAgICBjb25zdCBzaXplID0gTnVtYmVyKHNpemVTdHJpbmcpO1xuICAgIGhhbmRsZXJDaGVjayghaXNOYU4oc2l6ZSkpO1xuICAgIHJldHVybiBuZXcgUmVzdW1hYmxlVXBsb2FkU3RhdHVzKHNpemUsIGJsb2Iuc2l6ZSgpLCBzdGF0dXMgPT09ICdmaW5hbCcpO1xuICB9XG4gIGNvbnN0IG1ldGhvZCA9ICdQT1NUJztcbiAgY29uc3QgdGltZW91dCA9IHNlcnZpY2UubWF4VXBsb2FkUmV0cnlUaW1lO1xuICBjb25zdCByZXF1ZXN0SW5mbyA9IG5ldyBSZXF1ZXN0SW5mbyh1cmwsIG1ldGhvZCwgaGFuZGxlciwgdGltZW91dCk7XG4gIHJlcXVlc3RJbmZvLmhlYWRlcnMgPSBoZWFkZXJzO1xuICByZXF1ZXN0SW5mby5lcnJvckhhbmRsZXIgPSBzaGFyZWRFcnJvckhhbmRsZXIobG9jYXRpb24pO1xuICByZXR1cm4gcmVxdWVzdEluZm87XG59XG5cbi8qKlxuICogQW55IHVwbG9hZHMgdmlhIHRoZSByZXN1bWFibGUgdXBsb2FkIEFQSSBtdXN0IHRyYW5zZmVyIGEgbnVtYmVyIG9mIGJ5dGVzXG4gKiB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgdGhpcyBudW1iZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBSRVNVTUFCTEVfVVBMT0FEX0NIVU5LX1NJWkU6IG51bWJlciA9IDI1NiAqIDEwMjQ7XG5cbi8qKlxuICogQHBhcmFtIHVybCBGcm9tIGEgY2FsbCB0byBmYnMucmVxdWVzdHMuY3JlYXRlUmVzdW1hYmxlVXBsb2FkLlxuICogQHBhcmFtIGNodW5rU2l6ZSBOdW1iZXIgb2YgYnl0ZXMgdG8gdXBsb2FkLlxuICogQHBhcmFtIHN0YXR1cyBUaGUgcHJldmlvdXMgc3RhdHVzLlxuICogICAgIElmIG5vdCBwYXNzZWQgb3IgbnVsbCwgd2Ugc3RhcnQgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICogQHRocm93cyBmYnMuRXJyb3IgSWYgdGhlIHVwbG9hZCBpcyBhbHJlYWR5IGNvbXBsZXRlLCB0aGUgcGFzc2VkIGluIHN0YXR1c1xuICogICAgIGhhcyBhIGZpbmFsIHNpemUgaW5jb25zaXN0ZW50IHdpdGggdGhlIGJsb2IsIG9yIHRoZSBibG9iIGNhbm5vdCBiZSBzbGljZWRcbiAqICAgICBmb3IgdXBsb2FkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29udGludWVSZXN1bWFibGVVcGxvYWQoXG4gIGxvY2F0aW9uOiBMb2NhdGlvbixcbiAgc2VydmljZTogRmlyZWJhc2VTdG9yYWdlSW1wbCxcbiAgdXJsOiBzdHJpbmcsXG4gIGJsb2I6IEZic0Jsb2IsXG4gIGNodW5rU2l6ZTogbnVtYmVyLFxuICBtYXBwaW5nczogTWFwcGluZ3MsXG4gIHN0YXR1cz86IFJlc3VtYWJsZVVwbG9hZFN0YXR1cyB8IG51bGwsXG4gIHByb2dyZXNzQ2FsbGJhY2s/OiAoKHAxOiBudW1iZXIsIHAyOiBudW1iZXIpID0+IHZvaWQpIHwgbnVsbFxuKTogUmVxdWVzdEluZm88c3RyaW5nLCBSZXN1bWFibGVVcGxvYWRTdGF0dXM+IHtcbiAgLy8gVE9ETyhhbmR5c290byk6IHN0YW5kYXJkaXplIG9uIGludGVybmFsIGFzc2VydHNcbiAgLy8gYXNzZXJ0KCEob3B0X3N0YXR1cyAmJiBvcHRfc3RhdHVzLmZpbmFsaXplZCkpO1xuICBjb25zdCBzdGF0dXNfID0gbmV3IFJlc3VtYWJsZVVwbG9hZFN0YXR1cygwLCAwKTtcbiAgaWYgKHN0YXR1cykge1xuICAgIHN0YXR1c18uY3VycmVudCA9IHN0YXR1cy5jdXJyZW50O1xuICAgIHN0YXR1c18udG90YWwgPSBzdGF0dXMudG90YWw7XG4gIH0gZWxzZSB7XG4gICAgc3RhdHVzXy5jdXJyZW50ID0gMDtcbiAgICBzdGF0dXNfLnRvdGFsID0gYmxvYi5zaXplKCk7XG4gIH1cbiAgaWYgKGJsb2Iuc2l6ZSgpICE9PSBzdGF0dXNfLnRvdGFsKSB7XG4gICAgdGhyb3cgc2VydmVyRmlsZVdyb25nU2l6ZSgpO1xuICB9XG4gIGNvbnN0IGJ5dGVzTGVmdCA9IHN0YXR1c18udG90YWwgLSBzdGF0dXNfLmN1cnJlbnQ7XG4gIGxldCBieXRlc1RvVXBsb2FkID0gYnl0ZXNMZWZ0O1xuICBpZiAoY2h1bmtTaXplID4gMCkge1xuICAgIGJ5dGVzVG9VcGxvYWQgPSBNYXRoLm1pbihieXRlc1RvVXBsb2FkLCBjaHVua1NpemUpO1xuICB9XG4gIGNvbnN0IHN0YXJ0Qnl0ZSA9IHN0YXR1c18uY3VycmVudDtcbiAgY29uc3QgZW5kQnl0ZSA9IHN0YXJ0Qnl0ZSArIGJ5dGVzVG9VcGxvYWQ7XG4gIGxldCB1cGxvYWRDb21tYW5kID0gJyc7XG4gIGlmIChieXRlc1RvVXBsb2FkID09PSAwKSB7XG4gICAgdXBsb2FkQ29tbWFuZCA9ICdmaW5hbGl6ZSc7XG4gIH0gZWxzZSBpZiAoYnl0ZXNMZWZ0ID09PSBieXRlc1RvVXBsb2FkKSB7XG4gICAgdXBsb2FkQ29tbWFuZCA9ICd1cGxvYWQsIGZpbmFsaXplJztcbiAgfSBlbHNlIHtcbiAgICB1cGxvYWRDb21tYW5kID0gJ3VwbG9hZCc7XG4gIH1cbiAgY29uc3QgaGVhZGVycyA9IHtcbiAgICAnWC1Hb29nLVVwbG9hZC1Db21tYW5kJzogdXBsb2FkQ29tbWFuZCxcbiAgICAnWC1Hb29nLVVwbG9hZC1PZmZzZXQnOiBgJHtzdGF0dXNfLmN1cnJlbnR9YFxuICB9O1xuICBjb25zdCBib2R5ID0gYmxvYi5zbGljZShzdGFydEJ5dGUsIGVuZEJ5dGUpO1xuICBpZiAoYm9keSA9PT0gbnVsbCkge1xuICAgIHRocm93IGNhbm5vdFNsaWNlQmxvYigpO1xuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlcihcbiAgICB4aHI6IENvbm5lY3Rpb248c3RyaW5nPixcbiAgICB0ZXh0OiBzdHJpbmdcbiAgKTogUmVzdW1hYmxlVXBsb2FkU3RhdHVzIHtcbiAgICAvLyBUT0RPKGFuZHlzb3RvKTogVmVyaWZ5IHRoZSBNRDUgb2YgZWFjaCB1cGxvYWRlZCByYW5nZTpcbiAgICAvLyB0aGUgJ3gtcmFuZ2UtbWQ1JyBoZWFkZXIgY29tZXMgYmFjayB3aXRoIHN0YXR1cyBjb2RlIDMwOCByZXNwb25zZXMuXG4gICAgLy8gV2UnbGwgb25seSBiZSBhYmxlIHRvIGJhaWwgb3V0IHRob3VnaCwgYmVjYXVzZSB5b3UgY2FuJ3QgcmUtdXBsb2FkIGFcbiAgICAvLyByYW5nZSB0aGF0IHlvdSBwcmV2aW91c2x5IHVwbG9hZGVkLlxuICAgIGNvbnN0IHVwbG9hZFN0YXR1cyA9IGNoZWNrUmVzdW1lSGVhZGVyXyh4aHIsIFsnYWN0aXZlJywgJ2ZpbmFsJ10pO1xuICAgIGNvbnN0IG5ld0N1cnJlbnQgPSBzdGF0dXNfLmN1cnJlbnQgKyBieXRlc1RvVXBsb2FkO1xuICAgIGNvbnN0IHNpemUgPSBibG9iLnNpemUoKTtcbiAgICBsZXQgbWV0YWRhdGE7XG4gICAgaWYgKHVwbG9hZFN0YXR1cyA9PT0gJ2ZpbmFsJykge1xuICAgICAgbWV0YWRhdGEgPSBtZXRhZGF0YUhhbmRsZXIoc2VydmljZSwgbWFwcGluZ3MpKHhociwgdGV4dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1ldGFkYXRhID0gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBSZXN1bWFibGVVcGxvYWRTdGF0dXMoXG4gICAgICBuZXdDdXJyZW50LFxuICAgICAgc2l6ZSxcbiAgICAgIHVwbG9hZFN0YXR1cyA9PT0gJ2ZpbmFsJyxcbiAgICAgIG1ldGFkYXRhXG4gICAgKTtcbiAgfVxuICBjb25zdCBtZXRob2QgPSAnUE9TVCc7XG4gIGNvbnN0IHRpbWVvdXQgPSBzZXJ2aWNlLm1heFVwbG9hZFJldHJ5VGltZTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSBuZXcgUmVxdWVzdEluZm8odXJsLCBtZXRob2QsIGhhbmRsZXIsIHRpbWVvdXQpO1xuICByZXF1ZXN0SW5mby5oZWFkZXJzID0gaGVhZGVycztcbiAgcmVxdWVzdEluZm8uYm9keSA9IGJvZHkudXBsb2FkRGF0YSgpO1xuICByZXF1ZXN0SW5mby5wcm9ncmVzc0NhbGxiYWNrID0gcHJvZ3Jlc3NDYWxsYmFjayB8fCBudWxsO1xuICByZXF1ZXN0SW5mby5lcnJvckhhbmRsZXIgPSBzaGFyZWRFcnJvckhhbmRsZXIobG9jYXRpb24pO1xuICByZXR1cm4gcmVxdWVzdEluZm87XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IEVudW1lcmF0aW9ucyB1c2VkIGZvciB1cGxvYWQgdGFza3MuXG4gKi9cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIHRyaWdnZXJlZCBvbiBhIHRhc2suXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IHR5cGUgVGFza0V2ZW50ID0gc3RyaW5nO1xuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgdHJpZ2dlcmVkIG9uIGEgdGFzay5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgVGFza0V2ZW50ID0ge1xuICAvKipcbiAgICogRm9yIHRoaXMgZXZlbnQsXG4gICAqIDx1bD5cbiAgICogICA8bGk+VGhlIGBuZXh0YCBmdW5jdGlvbiBpcyB0cmlnZ2VyZWQgb24gcHJvZ3Jlc3MgdXBkYXRlcyBhbmQgd2hlbiB0aGVcbiAgICogICAgICAgdGFzayBpcyBwYXVzZWQvcmVzdW1lZCB3aXRoIGFuIGBVcGxvYWRUYXNrU25hcHNob3RgIGFzIHRoZSBmaXJzdFxuICAgKiAgICAgICBhcmd1bWVudC48L2xpPlxuICAgKiAgIDxsaT5UaGUgYGVycm9yYCBmdW5jdGlvbiBpcyB0cmlnZ2VyZWQgaWYgdGhlIHVwbG9hZCBpcyBjYW5jZWxlZCBvciBmYWlsc1xuICAgKiAgICAgICBmb3IgYW5vdGhlciByZWFzb24uPC9saT5cbiAgICogICA8bGk+VGhlIGBjb21wbGV0ZWAgZnVuY3Rpb24gaXMgdHJpZ2dlcmVkIGlmIHRoZSB1cGxvYWQgY29tcGxldGVzXG4gICAqICAgICAgIHN1Y2Nlc3NmdWxseS48L2xpPlxuICAgKiA8L3VsPlxuICAgKi9cbiAgU1RBVEVfQ0hBTkdFRDogJ3N0YXRlX2NoYW5nZWQnXG59O1xuXG4vKipcbiAqIEludGVybmFsIGVudW0gZm9yIHRhc2sgc3RhdGUuXG4gKi9cbmV4cG9ydCBjb25zdCBlbnVtIEludGVybmFsVGFza1N0YXRlIHtcbiAgUlVOTklORyA9ICdydW5uaW5nJyxcbiAgUEFVU0lORyA9ICdwYXVzaW5nJyxcbiAgUEFVU0VEID0gJ3BhdXNlZCcsXG4gIFNVQ0NFU1MgPSAnc3VjY2VzcycsXG4gIENBTkNFTElORyA9ICdjYW5jZWxpbmcnLFxuICBDQU5DRUxFRCA9ICdjYW5jZWxlZCcsXG4gIEVSUk9SID0gJ2Vycm9yJ1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgYSBydW5uaW5nIHVwbG9hZC5cbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgdHlwZSBUYXNrU3RhdGUgPSAodHlwZW9mIFRhc2tTdGF0ZSlba2V5b2YgdHlwZW9mIFRhc2tTdGF0ZV07XG5cbi8vIHR5cGUga2V5cyA9IGtleW9mIFRhc2tTdGF0ZVxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBjdXJyZW50IHN0YXRlIG9mIGEgcnVubmluZyB1cGxvYWQuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IFRhc2tTdGF0ZSA9IHtcbiAgLyoqIFRoZSB0YXNrIGlzIGN1cnJlbnRseSB0cmFuc2ZlcnJpbmcgZGF0YS4gKi9cbiAgUlVOTklORzogJ3J1bm5pbmcnLFxuXG4gIC8qKiBUaGUgdGFzayB3YXMgcGF1c2VkIGJ5IHRoZSB1c2VyLiAqL1xuICBQQVVTRUQ6ICdwYXVzZWQnLFxuXG4gIC8qKiBUaGUgdGFzayBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5LiAqL1xuICBTVUNDRVNTOiAnc3VjY2VzcycsXG5cbiAgLyoqIFRoZSB0YXNrIHdhcyBjYW5jZWxlZC4gKi9cbiAgQ0FOQ0VMRUQ6ICdjYW5jZWxlZCcsXG5cbiAgLyoqIFRoZSB0YXNrIGZhaWxlZCB3aXRoIGFuIGVycm9yLiAqL1xuICBFUlJPUjogJ2Vycm9yJ1xufSBhcyBjb25zdDtcblxuZXhwb3J0IGZ1bmN0aW9uIHRhc2tTdGF0ZUZyb21JbnRlcm5hbFRhc2tTdGF0ZShcbiAgc3RhdGU6IEludGVybmFsVGFza1N0YXRlXG4pOiBUYXNrU3RhdGUge1xuICBzd2l0Y2ggKHN0YXRlKSB7XG4gICAgY2FzZSBJbnRlcm5hbFRhc2tTdGF0ZS5SVU5OSU5HOlxuICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0lORzpcbiAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLkNBTkNFTElORzpcbiAgICAgIHJldHVybiBUYXNrU3RhdGUuUlVOTklORztcbiAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLlBBVVNFRDpcbiAgICAgIHJldHVybiBUYXNrU3RhdGUuUEFVU0VEO1xuICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuU1VDQ0VTUzpcbiAgICAgIHJldHVybiBUYXNrU3RhdGUuU1VDQ0VTUztcbiAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLkNBTkNFTEVEOlxuICAgICAgcmV0dXJuIFRhc2tTdGF0ZS5DQU5DRUxFRDtcbiAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLkVSUk9SOlxuICAgICAgcmV0dXJuIFRhc2tTdGF0ZS5FUlJPUjtcbiAgICBkZWZhdWx0OlxuICAgICAgLy8gVE9ETyhhbmR5c290byk6IGFzc2VydChmYWxzZSk7XG4gICAgICByZXR1cm4gVGFza1N0YXRlLkVSUk9SO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IGlzRnVuY3Rpb24gfSBmcm9tICcuL3R5cGUnO1xuaW1wb3J0IHsgU3RvcmFnZUVycm9yIH0gZnJvbSAnLi9lcnJvcic7XG5cbi8qKlxuICogRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgb25jZSBmb3IgZWFjaCB2YWx1ZSBpbiBhIHN0cmVhbSBvZiB2YWx1ZXMuXG4gKi9cbmV4cG9ydCB0eXBlIE5leHRGbjxUPiA9ICh2YWx1ZTogVCkgPT4gdm9pZDtcblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdpdGggYSBgU3RvcmFnZUVycm9yYFxuICogaWYgdGhlIGV2ZW50IHN0cmVhbSBlbmRzIGR1ZSB0byBhbiBlcnJvci5cbiAqL1xuZXhwb3J0IHR5cGUgRXJyb3JGbiA9IChlcnJvcjogU3RvcmFnZUVycm9yKSA9PiB2b2lkO1xuXG4vKipcbiAqIEEgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgaWYgdGhlIGV2ZW50IHN0cmVhbSBlbmRzIG5vcm1hbGx5LlxuICovXG5leHBvcnQgdHlwZSBDb21wbGV0ZUZuID0gKCkgPT4gdm9pZDtcblxuLyoqXG4gKiBVbnN1YnNjcmliZXMgZnJvbSBhIHN0cmVhbS5cbiAqL1xuZXhwb3J0IHR5cGUgVW5zdWJzY3JpYmUgPSAoKSA9PiB2b2lkO1xuXG4vKipcbiAqIEFuIG9ic2VydmVyIGlkZW50aWNhbCB0byB0aGUgYE9ic2VydmVyYCBkZWZpbmVkIGluIHBhY2thZ2VzL3V0aWwgZXhjZXB0IHRoZVxuICogZXJyb3IgcGFzc2VkIGludG8gdGhlIEVycm9yRm4gaXMgc3BlY2lmaWNhbGx5IGEgYFN0b3JhZ2VFcnJvcmAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RvcmFnZU9ic2VydmVyPFQ+IHtcbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIG9uY2UgZm9yIGVhY2ggdmFsdWUgaW4gdGhlIGV2ZW50IHN0cmVhbS5cbiAgICovXG4gIG5leHQ/OiBOZXh0Rm48VD47XG4gIC8qKlxuICAgKiBBIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdpdGggYSBgU3RvcmFnZUVycm9yYFxuICAgKiBpZiB0aGUgZXZlbnQgc3RyZWFtIGVuZHMgZHVlIHRvIGFuIGVycm9yLlxuICAgKi9cbiAgZXJyb3I/OiBFcnJvckZuO1xuICAvKipcbiAgICogQSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCBpZiB0aGUgZXZlbnQgc3RyZWFtIGVuZHMgbm9ybWFsbHkuXG4gICAqL1xuICBjb21wbGV0ZT86IENvbXBsZXRlRm47XG59XG5cbi8qKlxuICogU3Vic2NyaWJlcyB0byBhbiBldmVudCBzdHJlYW0uXG4gKi9cbmV4cG9ydCB0eXBlIFN1YnNjcmliZTxUPiA9IChcbiAgbmV4dD86IE5leHRGbjxUPiB8IFN0b3JhZ2VPYnNlcnZlcjxUPixcbiAgZXJyb3I/OiBFcnJvckZuLFxuICBjb21wbGV0ZT86IENvbXBsZXRlRm5cbikgPT4gVW5zdWJzY3JpYmU7XG5cbmV4cG9ydCBjbGFzcyBPYnNlcnZlcjxUPiBpbXBsZW1lbnRzIFN0b3JhZ2VPYnNlcnZlcjxUPiB7XG4gIG5leHQ/OiBOZXh0Rm48VD47XG4gIGVycm9yPzogRXJyb3JGbjtcbiAgY29tcGxldGU/OiBDb21wbGV0ZUZuO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG5leHRPck9ic2VydmVyPzogTmV4dEZuPFQ+IHwgU3RvcmFnZU9ic2VydmVyPFQ+LFxuICAgIGVycm9yPzogRXJyb3JGbixcbiAgICBjb21wbGV0ZT86IENvbXBsZXRlRm5cbiAgKSB7XG4gICAgY29uc3QgYXNGdW5jdGlvbnMgPVxuICAgICAgaXNGdW5jdGlvbihuZXh0T3JPYnNlcnZlcikgfHwgZXJyb3IgIT0gbnVsbCB8fCBjb21wbGV0ZSAhPSBudWxsO1xuICAgIGlmIChhc0Z1bmN0aW9ucykge1xuICAgICAgdGhpcy5uZXh0ID0gbmV4dE9yT2JzZXJ2ZXIgYXMgTmV4dEZuPFQ+O1xuICAgICAgdGhpcy5lcnJvciA9IGVycm9yID8/IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuY29tcGxldGUgPSBjb21wbGV0ZSA/PyB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG9ic2VydmVyID0gbmV4dE9yT2JzZXJ2ZXIgYXMge1xuICAgICAgICBuZXh0PzogTmV4dEZuPFQ+O1xuICAgICAgICBlcnJvcj86IEVycm9yRm47XG4gICAgICAgIGNvbXBsZXRlPzogQ29tcGxldGVGbjtcbiAgICAgIH07XG4gICAgICB0aGlzLm5leHQgPSBvYnNlcnZlci5uZXh0O1xuICAgICAgdGhpcy5lcnJvciA9IG9ic2VydmVyLmVycm9yO1xuICAgICAgdGhpcy5jb21wbGV0ZSA9IG9ic2VydmVyLmNvbXBsZXRlO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBmIHdpdGggaXRzIGFyZ3VtZW50cyBhc3luY2hyb25vdXNseSBhcyBhXG4gKiBtaWNyb3Rhc2ssIGkuZS4gYXMgc29vbiBhcyBwb3NzaWJsZSBhZnRlciB0aGUgY3VycmVudCBzY3JpcHQgcmV0dXJucyBiYWNrXG4gKiBpbnRvIGJyb3dzZXIgY29kZS5cbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHlwZXNcbmV4cG9ydCBmdW5jdGlvbiBhc3luYyhmOiBGdW5jdGlvbik6IEZ1bmN0aW9uIHtcbiAgcmV0dXJuICguLi5hcmdzVG9Gb3J3YXJkOiB1bmtub3duW10pID0+IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiBmKC4uLmFyZ3NUb0ZvcndhcmQpKTtcbiAgfTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBpc0Nsb3VkV29ya3N0YXRpb24gfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQge1xuICBDb25uZWN0aW9uLFxuICBDb25uZWN0aW9uVHlwZSxcbiAgRXJyb3JDb2RlXG59IGZyb20gJy4uLy4uL2ltcGxlbWVudGF0aW9uL2Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgaW50ZXJuYWxFcnJvciB9IGZyb20gJy4uLy4uL2ltcGxlbWVudGF0aW9uL2Vycm9yJztcblxuLyoqIEFuIG92ZXJyaWRlIGZvciB0aGUgdGV4dC1iYXNlZCBDb25uZWN0aW9uLiBVc2VkIGluIHRlc3RzLiAqL1xubGV0IHRleHRGYWN0b3J5T3ZlcnJpZGU6ICgoKSA9PiBDb25uZWN0aW9uPHN0cmluZz4pIHwgbnVsbCA9IG51bGw7XG5cbi8qKlxuICogTmV0d29yayBsYXllciB0aGF0IHdvcmtzIGluIE5vZGUuXG4gKlxuICogVGhpcyBuZXR3b3JrIGltcGxlbWVudGF0aW9uIHNob3VsZCBub3QgYmUgdXNlZCBpbiBicm93c2VycyBhcyBpdCBkb2VzIG5vdFxuICogc3VwcG9ydCBwcm9ncmVzcyB1cGRhdGVzLlxuICovXG5hYnN0cmFjdCBjbGFzcyBGZXRjaENvbm5lY3Rpb248VCBleHRlbmRzIENvbm5lY3Rpb25UeXBlPlxuICBpbXBsZW1lbnRzIENvbm5lY3Rpb248VD5cbntcbiAgcHJvdGVjdGVkIGVycm9yQ29kZV86IEVycm9yQ29kZTtcbiAgcHJvdGVjdGVkIHN0YXR1c0NvZGVfOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIHByb3RlY3RlZCBib2R5XzogQXJyYXlCdWZmZXIgfCB1bmRlZmluZWQ7XG4gIHByb3RlY3RlZCBlcnJvclRleHRfID0gJyc7XG4gIHByb3RlY3RlZCBoZWFkZXJzXzogSGVhZGVycyB8IHVuZGVmaW5lZDtcbiAgcHJvdGVjdGVkIHNlbnRfOiBib29sZWFuID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5lcnJvckNvZGVfID0gRXJyb3JDb2RlLk5PX0VSUk9SO1xuICB9XG5cbiAgYXN5bmMgc2VuZChcbiAgICB1cmw6IHN0cmluZyxcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBpc1VzaW5nRW11bGF0b3I6IGJvb2xlYW4sXG4gICAgYm9keT86IE5vZGVKUy5BcnJheUJ1ZmZlclZpZXcgfCBCbG9iIHwgc3RyaW5nLFxuICAgIGhlYWRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnNlbnRfKSB7XG4gICAgICB0aHJvdyBpbnRlcm5hbEVycm9yKCdjYW5ub3QgLnNlbmQoKSBtb3JlIHRoYW4gb25jZScpO1xuICAgIH1cbiAgICB0aGlzLnNlbnRfID0gdHJ1ZTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IG5ld0ZldGNoKFxuICAgICAgICB1cmwsXG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgaXNVc2luZ0VtdWxhdG9yLFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgICBib2R5XG4gICAgICApO1xuICAgICAgdGhpcy5oZWFkZXJzXyA9IHJlc3BvbnNlLmhlYWRlcnM7XG4gICAgICB0aGlzLnN0YXR1c0NvZGVfID0gcmVzcG9uc2Uuc3RhdHVzO1xuICAgICAgdGhpcy5lcnJvckNvZGVfID0gRXJyb3JDb2RlLk5PX0VSUk9SO1xuICAgICAgdGhpcy5ib2R5XyA9IGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5lcnJvclRleHRfID0gKGUgYXMgRXJyb3IpPy5tZXNzYWdlO1xuICAgICAgLy8gZW11bGF0ZSBYSFIgd2hpY2ggc2V0cyBzdGF0dXMgdG8gMCB3aGVuIGVuY291bnRlcmluZyBhIG5ldHdvcmsgZXJyb3JcbiAgICAgIHRoaXMuc3RhdHVzQ29kZV8gPSAwO1xuICAgICAgdGhpcy5lcnJvckNvZGVfID0gRXJyb3JDb2RlLk5FVFdPUktfRVJST1I7XG4gICAgfVxuICB9XG5cbiAgZ2V0RXJyb3JDb2RlKCk6IEVycm9yQ29kZSB7XG4gICAgaWYgKHRoaXMuZXJyb3JDb2RlXyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBpbnRlcm5hbEVycm9yKCdjYW5ub3QgLmdldEVycm9yQ29kZSgpIGJlZm9yZSByZWNlaXZpbmcgcmVzcG9uc2UnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JDb2RlXztcbiAgfVxuXG4gIGdldFN0YXR1cygpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLnN0YXR1c0NvZGVfID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IGludGVybmFsRXJyb3IoJ2Nhbm5vdCAuZ2V0U3RhdHVzKCkgYmVmb3JlIHJlY2VpdmluZyByZXNwb25zZScpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zdGF0dXNDb2RlXztcbiAgfVxuXG4gIGFic3RyYWN0IGdldFJlc3BvbnNlKCk6IFQ7XG5cbiAgZ2V0RXJyb3JUZXh0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JUZXh0XztcbiAgfVxuXG4gIGFib3J0KCk6IHZvaWQge1xuICAgIC8vIE5vdCBzdXBwb3J0ZWRcbiAgfVxuXG4gIGdldFJlc3BvbnNlSGVhZGVyKGhlYWRlcjogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLmhlYWRlcnNfKSB7XG4gICAgICB0aHJvdyBpbnRlcm5hbEVycm9yKFxuICAgICAgICAnY2Fubm90IC5nZXRSZXNwb25zZUhlYWRlcigpIGJlZm9yZSByZWNlaXZpbmcgcmVzcG9uc2UnXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5oZWFkZXJzXy5nZXQoaGVhZGVyKTtcbiAgfVxuXG4gIGFkZFVwbG9hZFByb2dyZXNzTGlzdGVuZXIobGlzdGVuZXI6IChwMTogUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIC8vIE5vdCBzdXBwb3J0ZWRcbiAgfVxuXG4gIHJlbW92ZVVwbG9hZFByb2dyZXNzTGlzdGVuZXIobGlzdGVuZXI6IChwMTogUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIC8vIE5vdCBzdXBwb3J0ZWRcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRmV0Y2hUZXh0Q29ubmVjdGlvbiBleHRlbmRzIEZldGNoQ29ubmVjdGlvbjxzdHJpbmc+IHtcbiAgZ2V0UmVzcG9uc2UoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuYm9keV8pIHtcbiAgICAgIHRocm93IGludGVybmFsRXJyb3IoJ2Nhbm5vdCAuZ2V0UmVzcG9uc2UoKSBiZWZvcmUgcmVjZWl2aW5nIHJlc3BvbnNlJyk7XG4gICAgfVxuICAgIHJldHVybiBCdWZmZXIuZnJvbSh0aGlzLmJvZHlfKS50b1N0cmluZygndXRmLTgnKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbmV3VGV4dENvbm5lY3Rpb24oKTogQ29ubmVjdGlvbjxzdHJpbmc+IHtcbiAgcmV0dXJuIHRleHRGYWN0b3J5T3ZlcnJpZGVcbiAgICA/IHRleHRGYWN0b3J5T3ZlcnJpZGUoKVxuICAgIDogbmV3IEZldGNoVGV4dENvbm5lY3Rpb24oKTtcbn1cblxuZXhwb3J0IGNsYXNzIEZldGNoQnl0ZXNDb25uZWN0aW9uIGV4dGVuZHMgRmV0Y2hDb25uZWN0aW9uPEFycmF5QnVmZmVyPiB7XG4gIGdldFJlc3BvbnNlKCk6IEFycmF5QnVmZmVyIHtcbiAgICBpZiAoIXRoaXMuYm9keV8pIHtcbiAgICAgIHRocm93IGludGVybmFsRXJyb3IoJ2Nhbm5vdCAuZ2V0UmVzcG9uc2UoKSBiZWZvcmUgc2VuZGluZycpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5ib2R5XztcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbmV3Qnl0ZXNDb25uZWN0aW9uKCk6IENvbm5lY3Rpb248QXJyYXlCdWZmZXI+IHtcbiAgcmV0dXJuIG5ldyBGZXRjaEJ5dGVzQ29ubmVjdGlvbigpO1xufVxuXG5leHBvcnQgY2xhc3MgRmV0Y2hTdHJlYW1Db25uZWN0aW9uIGV4dGVuZHMgRmV0Y2hDb25uZWN0aW9uPFxuICBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PlxuPiB7XG4gIHByaXZhdGUgc3RyZWFtXzogUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4gfCBudWxsID0gbnVsbDtcblxuICBhc3luYyBzZW5kKFxuICAgIHVybDogc3RyaW5nLFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIGlzVXNpbmdFbXVsYXRvcjogYm9vbGVhbixcbiAgICBib2R5PzogTm9kZUpTLkFycmF5QnVmZmVyVmlldyB8IEJsb2IgfCBzdHJpbmcsXG4gICAgaGVhZGVycz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz5cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuc2VudF8pIHtcbiAgICAgIHRocm93IGludGVybmFsRXJyb3IoJ2Nhbm5vdCAuc2VuZCgpIG1vcmUgdGhhbiBvbmNlJyk7XG4gICAgfVxuICAgIHRoaXMuc2VudF8gPSB0cnVlO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgbmV3RmV0Y2goXG4gICAgICAgIHVybCxcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBpc1VzaW5nRW11bGF0b3IsXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIGJvZHlcbiAgICAgICk7XG4gICAgICB0aGlzLmhlYWRlcnNfID0gcmVzcG9uc2UuaGVhZGVycztcbiAgICAgIHRoaXMuc3RhdHVzQ29kZV8gPSByZXNwb25zZS5zdGF0dXM7XG4gICAgICB0aGlzLmVycm9yQ29kZV8gPSBFcnJvckNvZGUuTk9fRVJST1I7XG4gICAgICB0aGlzLnN0cmVhbV8gPSByZXNwb25zZS5ib2R5IGFzIFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuZXJyb3JUZXh0XyA9IChlIGFzIEVycm9yKT8ubWVzc2FnZTtcbiAgICAgIC8vIGVtdWxhdGUgWEhSIHdoaWNoIHNldHMgc3RhdHVzIHRvIDAgd2hlbiBlbmNvdW50ZXJpbmcgYSBuZXR3b3JrIGVycm9yXG4gICAgICB0aGlzLnN0YXR1c0NvZGVfID0gMDtcbiAgICAgIHRoaXMuZXJyb3JDb2RlXyA9IEVycm9yQ29kZS5ORVRXT1JLX0VSUk9SO1xuICAgIH1cbiAgfVxuXG4gIGdldFJlc3BvbnNlKCk6IFJlYWRhYmxlU3RyZWFtIHtcbiAgICBpZiAoIXRoaXMuc3RyZWFtXykge1xuICAgICAgdGhyb3cgaW50ZXJuYWxFcnJvcignY2Fubm90IC5nZXRSZXNwb25zZSgpIGJlZm9yZSBzZW5kaW5nJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnN0cmVhbV87XG4gIH1cbn1cblxuZnVuY3Rpb24gbmV3RmV0Y2goXG4gIHVybDogc3RyaW5nLFxuICBtZXRob2Q6IHN0cmluZyxcbiAgaXNVc2luZ0VtdWxhdG9yOiBib29sZWFuLFxuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPixcbiAgYm9keT86IE5vZGVKUy5BcnJheUJ1ZmZlclZpZXcgfCBCbG9iIHwgc3RyaW5nXG4pOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gIGNvbnN0IGZldGNoQXJnczogUmVxdWVzdEluaXQgPSB7XG4gICAgbWV0aG9kLFxuICAgIGhlYWRlcnM6IGhlYWRlcnMgfHwge30sXG4gICAgYm9keTogYm9keSBhcyBOb2RlSlMuQXJyYXlCdWZmZXJWaWV3IHwgc3RyaW5nXG4gIH07XG4gIGlmIChpc0Nsb3VkV29ya3N0YXRpb24odXJsKSAmJiBpc1VzaW5nRW11bGF0b3IpIHtcbiAgICBmZXRjaEFyZ3MuY3JlZGVudGlhbHMgPSAnaW5jbHVkZSc7XG4gIH1cbiAgcmV0dXJuIGZldGNoKHVybCwgZmV0Y2hBcmdzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5ld1N0cmVhbUNvbm5lY3Rpb24oKTogQ29ubmVjdGlvbjxSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pj4ge1xuICByZXR1cm4gbmV3IEZldGNoU3RyZWFtQ29ubmVjdGlvbigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbmV3QmxvYkNvbm5lY3Rpb24oKTogQ29ubmVjdGlvbjxCbG9iPiB7XG4gIHRocm93IG5ldyBFcnJvcignQmxvYnMgYXJlIG5vdCBzdXBwb3J0ZWQgb24gTm9kZScpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5qZWN0VGVzdENvbm5lY3Rpb24oXG4gIGZhY3Rvcnk6ICgoKSA9PiBDb25uZWN0aW9uPHN0cmluZz4pIHwgbnVsbFxuKTogdm9pZCB7XG4gIHRleHRGYWN0b3J5T3ZlcnJpZGUgPSBmYWN0b3J5O1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgRGVmaW5lcyB0eXBlcyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBibG9iIHRyYW5zZmVyIHRhc2tzLlxuICovXG5cbmltcG9ydCB7IEZic0Jsb2IgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL2Jsb2InO1xuaW1wb3J0IHtcbiAgY2FuY2VsZWQsXG4gIFN0b3JhZ2VFcnJvckNvZGUsXG4gIFN0b3JhZ2VFcnJvcixcbiAgcmV0cnlMaW1pdEV4Y2VlZGVkXG59IGZyb20gJy4vaW1wbGVtZW50YXRpb24vZXJyb3InO1xuaW1wb3J0IHtcbiAgSW50ZXJuYWxUYXNrU3RhdGUsXG4gIFRhc2tFdmVudCxcbiAgVGFza1N0YXRlLFxuICB0YXNrU3RhdGVGcm9tSW50ZXJuYWxUYXNrU3RhdGVcbn0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi90YXNrZW51bXMnO1xuaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tICcuL21ldGFkYXRhJztcbmltcG9ydCB7XG4gIE9ic2VydmVyLFxuICBTdWJzY3JpYmUsXG4gIFVuc3Vic2NyaWJlLFxuICBTdG9yYWdlT2JzZXJ2ZXIgYXMgU3RvcmFnZU9ic2VydmVySW50ZXJuYWwsXG4gIE5leHRGblxufSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL29ic2VydmVyJztcbmltcG9ydCB7IFJlcXVlc3QgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3JlcXVlc3QnO1xuaW1wb3J0IHsgVXBsb2FkVGFza1NuYXBzaG90LCBTdG9yYWdlT2JzZXJ2ZXIgfSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBhc3luYyBhcyBmYnNBc3luYyB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vYXN5bmMnO1xuaW1wb3J0IHsgTWFwcGluZ3MsIGdldE1hcHBpbmdzIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi9tZXRhZGF0YSc7XG5pbXBvcnQge1xuICBjcmVhdGVSZXN1bWFibGVVcGxvYWQsXG4gIGdldFJlc3VtYWJsZVVwbG9hZFN0YXR1cyxcbiAgUkVTVU1BQkxFX1VQTE9BRF9DSFVOS19TSVpFLFxuICBSZXN1bWFibGVVcGxvYWRTdGF0dXMsXG4gIGNvbnRpbnVlUmVzdW1hYmxlVXBsb2FkLFxuICBnZXRNZXRhZGF0YSxcbiAgbXVsdGlwYXJ0VXBsb2FkXG59IGZyb20gJy4vaW1wbGVtZW50YXRpb24vcmVxdWVzdHMnO1xuaW1wb3J0IHsgUmVmZXJlbmNlIH0gZnJvbSAnLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgbmV3VGV4dENvbm5lY3Rpb24gfSBmcm9tICcuL3BsYXRmb3JtL2Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgaXNSZXRyeVN0YXR1c0NvZGUgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3V0aWxzJztcbmltcG9ydCB7IENvbXBsZXRlRm4gfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBERUZBVUxUX01JTl9TTEVFUF9USU1FX01JTExJUyB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vY29uc3RhbnRzJztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgYmxvYiBiZWluZyB1cGxvYWRlZC4gQ2FuIGJlIHVzZWQgdG8gcGF1c2UvcmVzdW1lL2NhbmNlbCB0aGVcbiAqIHVwbG9hZCBhbmQgbWFuYWdlIGNhbGxiYWNrcyBmb3IgdmFyaW91cyBldmVudHMuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIFVwbG9hZFRhc2sge1xuICBwcml2YXRlIF9yZWY6IFJlZmVyZW5jZTtcbiAgLyoqXG4gICAqIFRoZSBkYXRhIHRvIGJlIHVwbG9hZGVkLlxuICAgKi9cbiAgX2Jsb2I6IEZic0Jsb2I7XG4gIC8qKlxuICAgKiBNZXRhZGF0YSByZWxhdGVkIHRvIHRoZSB1cGxvYWQuXG4gICAqL1xuICBfbWV0YWRhdGE6IE1ldGFkYXRhIHwgbnVsbDtcbiAgcHJpdmF0ZSBfbWFwcGluZ3M6IE1hcHBpbmdzO1xuICAvKipcbiAgICogTnVtYmVyIG9mIGJ5dGVzIHRyYW5zZmVycmVkIHNvIGZhci5cbiAgICovXG4gIF90cmFuc2ZlcnJlZDogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSBfbmVlZFRvRmV0Y2hTdGF0dXM6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBfbmVlZFRvRmV0Y2hNZXRhZGF0YTogYm9vbGVhbiA9IGZhbHNlO1xuICBwcml2YXRlIF9vYnNlcnZlcnM6IEFycmF5PFN0b3JhZ2VPYnNlcnZlckludGVybmFsPFVwbG9hZFRhc2tTbmFwc2hvdD4+ID0gW107XG4gIHByaXZhdGUgX3Jlc3VtYWJsZTogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFVwbG9hZCBzdGF0ZS5cbiAgICovXG4gIF9zdGF0ZTogSW50ZXJuYWxUYXNrU3RhdGU7XG4gIHByaXZhdGUgX2Vycm9yPzogU3RvcmFnZUVycm9yID0gdW5kZWZpbmVkO1xuICBwcml2YXRlIF91cGxvYWRVcmw/OiBzdHJpbmcgPSB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX3JlcXVlc3Q/OiBSZXF1ZXN0PHVua25vd24+ID0gdW5kZWZpbmVkO1xuICBwcml2YXRlIF9jaHVua011bHRpcGxpZXI6IG51bWJlciA9IDE7XG4gIHByaXZhdGUgX2Vycm9ySGFuZGxlcjogKHAxOiBTdG9yYWdlRXJyb3IpID0+IHZvaWQ7XG4gIHByaXZhdGUgX21ldGFkYXRhRXJyb3JIYW5kbGVyOiAocDE6IFN0b3JhZ2VFcnJvcikgPT4gdm9pZDtcbiAgcHJpdmF0ZSBfcmVzb2x2ZT86IChwMTogVXBsb2FkVGFza1NuYXBzaG90KSA9PiB2b2lkID0gdW5kZWZpbmVkO1xuICBwcml2YXRlIF9yZWplY3Q/OiAocDE6IFN0b3JhZ2VFcnJvcikgPT4gdm9pZCA9IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBwZW5kaW5nVGltZW91dD86IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+O1xuICBwcml2YXRlIF9wcm9taXNlOiBQcm9taXNlPFVwbG9hZFRhc2tTbmFwc2hvdD47XG5cbiAgcHJpdmF0ZSBzbGVlcFRpbWU6IG51bWJlcjtcblxuICBwcml2YXRlIG1heFNsZWVwVGltZTogbnVtYmVyO1xuXG4gIGlzRXhwb25lbnRpYWxCYWNrb2ZmRXhwaXJlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zbGVlcFRpbWUgPiB0aGlzLm1heFNsZWVwVGltZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gcmVmIC0gVGhlIGZpcmViYXNlU3RvcmFnZS5SZWZlcmVuY2Ugb2JqZWN0IHRoaXMgdGFzayBjYW1lXG4gICAqICAgICBmcm9tLCB1bnR5cGVkIHRvIGF2b2lkIGN5Y2xpYyBkZXBlbmRlbmNpZXMuXG4gICAqIEBwYXJhbSBibG9iIC0gVGhlIGJsb2IgdG8gdXBsb2FkLlxuICAgKi9cbiAgY29uc3RydWN0b3IocmVmOiBSZWZlcmVuY2UsIGJsb2I6IEZic0Jsb2IsIG1ldGFkYXRhOiBNZXRhZGF0YSB8IG51bGwgPSBudWxsKSB7XG4gICAgdGhpcy5fcmVmID0gcmVmO1xuICAgIHRoaXMuX2Jsb2IgPSBibG9iO1xuICAgIHRoaXMuX21ldGFkYXRhID0gbWV0YWRhdGE7XG4gICAgdGhpcy5fbWFwcGluZ3MgPSBnZXRNYXBwaW5ncygpO1xuICAgIHRoaXMuX3Jlc3VtYWJsZSA9IHRoaXMuX3Nob3VsZERvUmVzdW1hYmxlKHRoaXMuX2Jsb2IpO1xuICAgIHRoaXMuX3N0YXRlID0gSW50ZXJuYWxUYXNrU3RhdGUuUlVOTklORztcbiAgICB0aGlzLl9lcnJvckhhbmRsZXIgPSBlcnJvciA9PiB7XG4gICAgICB0aGlzLl9yZXF1ZXN0ID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5fY2h1bmtNdWx0aXBsaWVyID0gMTtcbiAgICAgIGlmIChlcnJvci5fY29kZUVxdWFscyhTdG9yYWdlRXJyb3JDb2RlLkNBTkNFTEVEKSkge1xuICAgICAgICB0aGlzLl9uZWVkVG9GZXRjaFN0YXR1cyA9IHRydWU7XG4gICAgICAgIHRoaXMuY29tcGxldGVUcmFuc2l0aW9uc18oKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGJhY2tvZmZFeHBpcmVkID0gdGhpcy5pc0V4cG9uZW50aWFsQmFja29mZkV4cGlyZWQoKTtcbiAgICAgICAgaWYgKGlzUmV0cnlTdGF0dXNDb2RlKGVycm9yLnN0YXR1cywgW10pKSB7XG4gICAgICAgICAgaWYgKGJhY2tvZmZFeHBpcmVkKSB7XG4gICAgICAgICAgICBlcnJvciA9IHJldHJ5TGltaXRFeGNlZWRlZCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNsZWVwVGltZSA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICB0aGlzLnNsZWVwVGltZSAqIDIsXG4gICAgICAgICAgICAgIERFRkFVTFRfTUlOX1NMRUVQX1RJTUVfTUlMTElTXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5fbmVlZFRvRmV0Y2hTdGF0dXMgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jb21wbGV0ZVRyYW5zaXRpb25zXygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9lcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9uKEludGVybmFsVGFza1N0YXRlLkVSUk9SKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHRoaXMuX21ldGFkYXRhRXJyb3JIYW5kbGVyID0gZXJyb3IgPT4ge1xuICAgICAgdGhpcy5fcmVxdWVzdCA9IHVuZGVmaW5lZDtcbiAgICAgIGlmIChlcnJvci5fY29kZUVxdWFscyhTdG9yYWdlRXJyb3JDb2RlLkNBTkNFTEVEKSkge1xuICAgICAgICB0aGlzLmNvbXBsZXRlVHJhbnNpdGlvbnNfKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9lcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLl90cmFuc2l0aW9uKEludGVybmFsVGFza1N0YXRlLkVSUk9SKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHRoaXMuc2xlZXBUaW1lID0gMDtcbiAgICB0aGlzLm1heFNsZWVwVGltZSA9IHRoaXMuX3JlZi5zdG9yYWdlLm1heFVwbG9hZFJldHJ5VGltZTtcbiAgICB0aGlzLl9wcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5fcmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICB0aGlzLl9yZWplY3QgPSByZWplY3Q7XG4gICAgICB0aGlzLl9zdGFydCgpO1xuICAgIH0pO1xuXG4gICAgLy8gUHJldmVudCB1bmNhdWdodCByZWplY3Rpb25zIG9uIHRoZSBpbnRlcm5hbCBwcm9taXNlIGZyb20gYnViYmxpbmcgb3V0XG4gICAgLy8gdG8gdGhlIHRvcCBsZXZlbCB3aXRoIGEgZHVtbXkgaGFuZGxlci5cbiAgICB0aGlzLl9wcm9taXNlLnRoZW4obnVsbCwgKCkgPT4ge30pO1xuICB9XG5cbiAgcHJpdmF0ZSBfbWFrZVByb2dyZXNzQ2FsbGJhY2soKTogKHAxOiBudW1iZXIsIHAyOiBudW1iZXIpID0+IHZvaWQge1xuICAgIGNvbnN0IHNpemVCZWZvcmUgPSB0aGlzLl90cmFuc2ZlcnJlZDtcbiAgICByZXR1cm4gbG9hZGVkID0+IHRoaXMuX3VwZGF0ZVByb2dyZXNzKHNpemVCZWZvcmUgKyBsb2FkZWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2hvdWxkRG9SZXN1bWFibGUoYmxvYjogRmJzQmxvYik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBibG9iLnNpemUoKSA+IDI1NiAqIDEwMjQ7XG4gIH1cblxuICBwcml2YXRlIF9zdGFydCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fc3RhdGUgIT09IEludGVybmFsVGFza1N0YXRlLlJVTk5JTkcpIHtcbiAgICAgIC8vIFRoaXMgY2FuIGhhcHBlbiBpZiBzb21lb25lIHBhdXNlcyB1cyBpbiBhIHJlc3VtZSBjYWxsYmFjaywgZm9yIGV4YW1wbGUuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLl9yZXF1ZXN0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMuX3Jlc3VtYWJsZSkge1xuICAgICAgaWYgKHRoaXMuX3VwbG9hZFVybCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuX2NyZWF0ZVJlc3VtYWJsZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuX25lZWRUb0ZldGNoU3RhdHVzKSB7XG4gICAgICAgICAgdGhpcy5fZmV0Y2hTdGF0dXMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodGhpcy5fbmVlZFRvRmV0Y2hNZXRhZGF0YSkge1xuICAgICAgICAgICAgLy8gSGFwcGVucyBpZiB3ZSBtaXNzIHRoZSBtZXRhZGF0YSBvbiB1cGxvYWQgY29tcGxldGlvbi5cbiAgICAgICAgICAgIHRoaXMuX2ZldGNoTWV0YWRhdGEoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdUaW1lb3V0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB0aGlzLl9jb250aW51ZVVwbG9hZCgpO1xuICAgICAgICAgICAgfSwgdGhpcy5zbGVlcFRpbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9vbmVTaG90VXBsb2FkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfcmVzb2x2ZVRva2VuKFxuICAgIGNhbGxiYWNrOiAoYXV0aFRva2VuOiBzdHJpbmcgfCBudWxsLCBhcHBDaGVja1Rva2VuOiBzdHJpbmcgfCBudWxsKSA9PiB2b2lkXG4gICk6IHZvaWQge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZmxvYXRpbmctcHJvbWlzZXNcbiAgICBQcm9taXNlLmFsbChbXG4gICAgICB0aGlzLl9yZWYuc3RvcmFnZS5fZ2V0QXV0aFRva2VuKCksXG4gICAgICB0aGlzLl9yZWYuc3RvcmFnZS5fZ2V0QXBwQ2hlY2tUb2tlbigpXG4gICAgXSkudGhlbigoW2F1dGhUb2tlbiwgYXBwQ2hlY2tUb2tlbl0pID0+IHtcbiAgICAgIHN3aXRjaCAodGhpcy5fc3RhdGUpIHtcbiAgICAgICAgY2FzZSBJbnRlcm5hbFRhc2tTdGF0ZS5SVU5OSU5HOlxuICAgICAgICAgIGNhbGxiYWNrKGF1dGhUb2tlbiwgYXBwQ2hlY2tUb2tlbik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuQ0FOQ0VMSU5HOlxuICAgICAgICAgIHRoaXMuX3RyYW5zaXRpb24oSW50ZXJuYWxUYXNrU3RhdGUuQ0FOQ0VMRUQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLlBBVVNJTkc6XG4gICAgICAgICAgdGhpcy5fdHJhbnNpdGlvbihJbnRlcm5hbFRhc2tTdGF0ZS5QQVVTRUQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gVE9ETyhhbmR5c290byk6IGFzc2VydCBmYWxzZVxuXG4gIHByaXZhdGUgX2NyZWF0ZVJlc3VtYWJsZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9yZXNvbHZlVG9rZW4oKGF1dGhUb2tlbiwgYXBwQ2hlY2tUb2tlbikgPT4ge1xuICAgICAgY29uc3QgcmVxdWVzdEluZm8gPSBjcmVhdGVSZXN1bWFibGVVcGxvYWQoXG4gICAgICAgIHRoaXMuX3JlZi5zdG9yYWdlLFxuICAgICAgICB0aGlzLl9yZWYuX2xvY2F0aW9uLFxuICAgICAgICB0aGlzLl9tYXBwaW5ncyxcbiAgICAgICAgdGhpcy5fYmxvYixcbiAgICAgICAgdGhpcy5fbWV0YWRhdGFcbiAgICAgICk7XG4gICAgICBjb25zdCBjcmVhdGVSZXF1ZXN0ID0gdGhpcy5fcmVmLnN0b3JhZ2UuX21ha2VSZXF1ZXN0KFxuICAgICAgICByZXF1ZXN0SW5mbyxcbiAgICAgICAgbmV3VGV4dENvbm5lY3Rpb24sXG4gICAgICAgIGF1dGhUb2tlbixcbiAgICAgICAgYXBwQ2hlY2tUb2tlblxuICAgICAgKTtcbiAgICAgIHRoaXMuX3JlcXVlc3QgPSBjcmVhdGVSZXF1ZXN0O1xuICAgICAgY3JlYXRlUmVxdWVzdC5nZXRQcm9taXNlKCkudGhlbigodXJsOiBzdHJpbmcpID0+IHtcbiAgICAgICAgdGhpcy5fcmVxdWVzdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fdXBsb2FkVXJsID0gdXJsO1xuICAgICAgICB0aGlzLl9uZWVkVG9GZXRjaFN0YXR1cyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmNvbXBsZXRlVHJhbnNpdGlvbnNfKCk7XG4gICAgICB9LCB0aGlzLl9lcnJvckhhbmRsZXIpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfZmV0Y2hTdGF0dXMoKTogdm9pZCB7XG4gICAgLy8gVE9ETyhhbmR5c290byk6IGFzc2VydCh0aGlzLnVwbG9hZFVybF8gIT09IG51bGwpO1xuICAgIGNvbnN0IHVybCA9IHRoaXMuX3VwbG9hZFVybCBhcyBzdHJpbmc7XG4gICAgdGhpcy5fcmVzb2x2ZVRva2VuKChhdXRoVG9rZW4sIGFwcENoZWNrVG9rZW4pID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3RJbmZvID0gZ2V0UmVzdW1hYmxlVXBsb2FkU3RhdHVzKFxuICAgICAgICB0aGlzLl9yZWYuc3RvcmFnZSxcbiAgICAgICAgdGhpcy5fcmVmLl9sb2NhdGlvbixcbiAgICAgICAgdXJsLFxuICAgICAgICB0aGlzLl9ibG9iXG4gICAgICApO1xuICAgICAgY29uc3Qgc3RhdHVzUmVxdWVzdCA9IHRoaXMuX3JlZi5zdG9yYWdlLl9tYWtlUmVxdWVzdChcbiAgICAgICAgcmVxdWVzdEluZm8sXG4gICAgICAgIG5ld1RleHRDb25uZWN0aW9uLFxuICAgICAgICBhdXRoVG9rZW4sXG4gICAgICAgIGFwcENoZWNrVG9rZW5cbiAgICAgICk7XG4gICAgICB0aGlzLl9yZXF1ZXN0ID0gc3RhdHVzUmVxdWVzdDtcbiAgICAgIHN0YXR1c1JlcXVlc3QuZ2V0UHJvbWlzZSgpLnRoZW4oc3RhdHVzID0+IHtcbiAgICAgICAgc3RhdHVzID0gc3RhdHVzIGFzIFJlc3VtYWJsZVVwbG9hZFN0YXR1cztcbiAgICAgICAgdGhpcy5fcmVxdWVzdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJvZ3Jlc3Moc3RhdHVzLmN1cnJlbnQpO1xuICAgICAgICB0aGlzLl9uZWVkVG9GZXRjaFN0YXR1cyA9IGZhbHNlO1xuICAgICAgICBpZiAoc3RhdHVzLmZpbmFsaXplZCkge1xuICAgICAgICAgIHRoaXMuX25lZWRUb0ZldGNoTWV0YWRhdGEgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29tcGxldGVUcmFuc2l0aW9uc18oKTtcbiAgICAgIH0sIHRoaXMuX2Vycm9ySGFuZGxlcik7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9jb250aW51ZVVwbG9hZCgpOiB2b2lkIHtcbiAgICBjb25zdCBjaHVua1NpemUgPSBSRVNVTUFCTEVfVVBMT0FEX0NIVU5LX1NJWkUgKiB0aGlzLl9jaHVua011bHRpcGxpZXI7XG4gICAgY29uc3Qgc3RhdHVzID0gbmV3IFJlc3VtYWJsZVVwbG9hZFN0YXR1cyhcbiAgICAgIHRoaXMuX3RyYW5zZmVycmVkLFxuICAgICAgdGhpcy5fYmxvYi5zaXplKClcbiAgICApO1xuXG4gICAgLy8gVE9ETyhhbmR5c290byk6IGFzc2VydCh0aGlzLnVwbG9hZFVybF8gIT09IG51bGwpO1xuICAgIGNvbnN0IHVybCA9IHRoaXMuX3VwbG9hZFVybCBhcyBzdHJpbmc7XG4gICAgdGhpcy5fcmVzb2x2ZVRva2VuKChhdXRoVG9rZW4sIGFwcENoZWNrVG9rZW4pID0+IHtcbiAgICAgIGxldCByZXF1ZXN0SW5mbztcbiAgICAgIHRyeSB7XG4gICAgICAgIHJlcXVlc3RJbmZvID0gY29udGludWVSZXN1bWFibGVVcGxvYWQoXG4gICAgICAgICAgdGhpcy5fcmVmLl9sb2NhdGlvbixcbiAgICAgICAgICB0aGlzLl9yZWYuc3RvcmFnZSxcbiAgICAgICAgICB1cmwsXG4gICAgICAgICAgdGhpcy5fYmxvYixcbiAgICAgICAgICBjaHVua1NpemUsXG4gICAgICAgICAgdGhpcy5fbWFwcGluZ3MsXG4gICAgICAgICAgc3RhdHVzLFxuICAgICAgICAgIHRoaXMuX21ha2VQcm9ncmVzc0NhbGxiYWNrKClcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5fZXJyb3IgPSBlIGFzIFN0b3JhZ2VFcnJvcjtcbiAgICAgICAgdGhpcy5fdHJhbnNpdGlvbihJbnRlcm5hbFRhc2tTdGF0ZS5FUlJPUik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwbG9hZFJlcXVlc3QgPSB0aGlzLl9yZWYuc3RvcmFnZS5fbWFrZVJlcXVlc3QoXG4gICAgICAgIHJlcXVlc3RJbmZvLFxuICAgICAgICBuZXdUZXh0Q29ubmVjdGlvbixcbiAgICAgICAgYXV0aFRva2VuLFxuICAgICAgICBhcHBDaGVja1Rva2VuLFxuICAgICAgICAvKnJldHJ5PSovIGZhbHNlIC8vIFVwbG9hZCByZXF1ZXN0cyBzaG91bGQgbm90IGJlIHJldHJpZWQgYXMgZWFjaCByZXRyeSBzaG91bGQgYmUgcHJlY2VkZWQgYnkgYW5vdGhlciBxdWVyeSByZXF1ZXN0LiBXaGljaCBpcyBoYW5kbGVkIGluIHRoaXMgZmlsZS5cbiAgICAgICk7XG4gICAgICB0aGlzLl9yZXF1ZXN0ID0gdXBsb2FkUmVxdWVzdDtcbiAgICAgIHVwbG9hZFJlcXVlc3QuZ2V0UHJvbWlzZSgpLnRoZW4oKG5ld1N0YXR1czogUmVzdW1hYmxlVXBsb2FkU3RhdHVzKSA9PiB7XG4gICAgICAgIHRoaXMuX2luY3JlYXNlTXVsdGlwbGllcigpO1xuICAgICAgICB0aGlzLl9yZXF1ZXN0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl91cGRhdGVQcm9ncmVzcyhuZXdTdGF0dXMuY3VycmVudCk7XG4gICAgICAgIGlmIChuZXdTdGF0dXMuZmluYWxpemVkKSB7XG4gICAgICAgICAgdGhpcy5fbWV0YWRhdGEgPSBuZXdTdGF0dXMubWV0YWRhdGE7XG4gICAgICAgICAgdGhpcy5fdHJhbnNpdGlvbihJbnRlcm5hbFRhc2tTdGF0ZS5TVUNDRVNTKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmNvbXBsZXRlVHJhbnNpdGlvbnNfKCk7XG4gICAgICAgIH1cbiAgICAgIH0sIHRoaXMuX2Vycm9ySGFuZGxlcik7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9pbmNyZWFzZU11bHRpcGxpZXIoKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFNpemUgPSBSRVNVTUFCTEVfVVBMT0FEX0NIVU5LX1NJWkUgKiB0aGlzLl9jaHVua011bHRpcGxpZXI7XG5cbiAgICAvLyBNYXggY2h1bmsgc2l6ZSBpcyAzMk0uXG4gICAgaWYgKGN1cnJlbnRTaXplICogMiA8IDMyICogMTAyNCAqIDEwMjQpIHtcbiAgICAgIHRoaXMuX2NodW5rTXVsdGlwbGllciAqPSAyO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2ZldGNoTWV0YWRhdGEoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVzb2x2ZVRva2VuKChhdXRoVG9rZW4sIGFwcENoZWNrVG9rZW4pID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3RJbmZvID0gZ2V0TWV0YWRhdGEoXG4gICAgICAgIHRoaXMuX3JlZi5zdG9yYWdlLFxuICAgICAgICB0aGlzLl9yZWYuX2xvY2F0aW9uLFxuICAgICAgICB0aGlzLl9tYXBwaW5nc1xuICAgICAgKTtcbiAgICAgIGNvbnN0IG1ldGFkYXRhUmVxdWVzdCA9IHRoaXMuX3JlZi5zdG9yYWdlLl9tYWtlUmVxdWVzdChcbiAgICAgICAgcmVxdWVzdEluZm8sXG4gICAgICAgIG5ld1RleHRDb25uZWN0aW9uLFxuICAgICAgICBhdXRoVG9rZW4sXG4gICAgICAgIGFwcENoZWNrVG9rZW5cbiAgICAgICk7XG4gICAgICB0aGlzLl9yZXF1ZXN0ID0gbWV0YWRhdGFSZXF1ZXN0O1xuICAgICAgbWV0YWRhdGFSZXF1ZXN0LmdldFByb21pc2UoKS50aGVuKG1ldGFkYXRhID0+IHtcbiAgICAgICAgdGhpcy5fcmVxdWVzdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5fbWV0YWRhdGEgPSBtZXRhZGF0YTtcbiAgICAgICAgdGhpcy5fdHJhbnNpdGlvbihJbnRlcm5hbFRhc2tTdGF0ZS5TVUNDRVNTKTtcbiAgICAgIH0sIHRoaXMuX21ldGFkYXRhRXJyb3JIYW5kbGVyKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX29uZVNob3RVcGxvYWQoKTogdm9pZCB7XG4gICAgdGhpcy5fcmVzb2x2ZVRva2VuKChhdXRoVG9rZW4sIGFwcENoZWNrVG9rZW4pID0+IHtcbiAgICAgIGNvbnN0IHJlcXVlc3RJbmZvID0gbXVsdGlwYXJ0VXBsb2FkKFxuICAgICAgICB0aGlzLl9yZWYuc3RvcmFnZSxcbiAgICAgICAgdGhpcy5fcmVmLl9sb2NhdGlvbixcbiAgICAgICAgdGhpcy5fbWFwcGluZ3MsXG4gICAgICAgIHRoaXMuX2Jsb2IsXG4gICAgICAgIHRoaXMuX21ldGFkYXRhXG4gICAgICApO1xuICAgICAgY29uc3QgbXVsdGlwYXJ0UmVxdWVzdCA9IHRoaXMuX3JlZi5zdG9yYWdlLl9tYWtlUmVxdWVzdChcbiAgICAgICAgcmVxdWVzdEluZm8sXG4gICAgICAgIG5ld1RleHRDb25uZWN0aW9uLFxuICAgICAgICBhdXRoVG9rZW4sXG4gICAgICAgIGFwcENoZWNrVG9rZW5cbiAgICAgICk7XG4gICAgICB0aGlzLl9yZXF1ZXN0ID0gbXVsdGlwYXJ0UmVxdWVzdDtcbiAgICAgIG11bHRpcGFydFJlcXVlc3QuZ2V0UHJvbWlzZSgpLnRoZW4obWV0YWRhdGEgPT4ge1xuICAgICAgICB0aGlzLl9yZXF1ZXN0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9tZXRhZGF0YSA9IG1ldGFkYXRhO1xuICAgICAgICB0aGlzLl91cGRhdGVQcm9ncmVzcyh0aGlzLl9ibG9iLnNpemUoKSk7XG4gICAgICAgIHRoaXMuX3RyYW5zaXRpb24oSW50ZXJuYWxUYXNrU3RhdGUuU1VDQ0VTUyk7XG4gICAgICB9LCB0aGlzLl9lcnJvckhhbmRsZXIpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlUHJvZ3Jlc3ModHJhbnNmZXJyZWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IG9sZCA9IHRoaXMuX3RyYW5zZmVycmVkO1xuICAgIHRoaXMuX3RyYW5zZmVycmVkID0gdHJhbnNmZXJyZWQ7XG5cbiAgICAvLyBBIHByb2dyZXNzIHVwZGF0ZSBjYW4gbWFrZSB0aGUgXCJ0cmFuc2ZlcnJlZFwiIHZhbHVlIHNtYWxsZXIgKGUuZy4gYVxuICAgIC8vIHBhcnRpYWwgdXBsb2FkIG5vdCBjb21wbGV0ZWQgYnkgc2VydmVyLCBhZnRlciB3aGljaCB0aGUgXCJ0cmFuc2ZlcnJlZFwiXG4gICAgLy8gdmFsdWUgbWF5IHJlc2V0IHRvIHRoZSB2YWx1ZSBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSByZXF1ZXN0KS5cbiAgICBpZiAodGhpcy5fdHJhbnNmZXJyZWQgIT09IG9sZCkge1xuICAgICAgdGhpcy5fbm90aWZ5T2JzZXJ2ZXJzKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfdHJhbnNpdGlvbihzdGF0ZTogSW50ZXJuYWxUYXNrU3RhdGUpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fc3RhdGUgPT09IHN0YXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHN3aXRjaCAoc3RhdGUpIHtcbiAgICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuQ0FOQ0VMSU5HOlxuICAgICAgY2FzZSBJbnRlcm5hbFRhc2tTdGF0ZS5QQVVTSU5HOlxuICAgICAgICAvLyBUT0RPKGFuZHlzb3RvKTpcbiAgICAgICAgLy8gYXNzZXJ0KHRoaXMuc3RhdGVfID09PSBJbnRlcm5hbFRhc2tTdGF0ZS5SVU5OSU5HIHx8XG4gICAgICAgIC8vICAgICAgICB0aGlzLnN0YXRlXyA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0lORyk7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gc3RhdGU7XG4gICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aGlzLl9yZXF1ZXN0LmNhbmNlbCgpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMucGVuZGluZ1RpbWVvdXQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5wZW5kaW5nVGltZW91dCk7XG4gICAgICAgICAgdGhpcy5wZW5kaW5nVGltZW91dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB0aGlzLmNvbXBsZXRlVHJhbnNpdGlvbnNfKCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLlJVTk5JTkc6XG4gICAgICAgIC8vIFRPRE8oYW5keXNvdG8pOlxuICAgICAgICAvLyBhc3NlcnQodGhpcy5zdGF0ZV8gPT09IEludGVybmFsVGFza1N0YXRlLlBBVVNFRCB8fFxuICAgICAgICAvLyAgICAgICAgdGhpcy5zdGF0ZV8gPT09IEludGVybmFsVGFza1N0YXRlLlBBVVNJTkcpO1xuICAgICAgICBjb25zdCB3YXNQYXVzZWQgPSB0aGlzLl9zdGF0ZSA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0VEO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9IHN0YXRlO1xuICAgICAgICBpZiAod2FzUGF1c2VkKSB7XG4gICAgICAgICAgdGhpcy5fbm90aWZ5T2JzZXJ2ZXJzKCk7XG4gICAgICAgICAgdGhpcy5fc3RhcnQoKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0VEOlxuICAgICAgICAvLyBUT0RPKGFuZHlzb3RvKTpcbiAgICAgICAgLy8gYXNzZXJ0KHRoaXMuc3RhdGVfID09PSBJbnRlcm5hbFRhc2tTdGF0ZS5QQVVTSU5HKTtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgdGhpcy5fbm90aWZ5T2JzZXJ2ZXJzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBJbnRlcm5hbFRhc2tTdGF0ZS5DQU5DRUxFRDpcbiAgICAgICAgLy8gVE9ETyhhbmR5c290byk6XG4gICAgICAgIC8vIGFzc2VydCh0aGlzLnN0YXRlXyA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0VEIHx8XG4gICAgICAgIC8vICAgICAgICB0aGlzLnN0YXRlXyA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuQ0FOQ0VMSU5HKTtcbiAgICAgICAgdGhpcy5fZXJyb3IgPSBjYW5jZWxlZCgpO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9IHN0YXRlO1xuICAgICAgICB0aGlzLl9ub3RpZnlPYnNlcnZlcnMoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLkVSUk9SOlxuICAgICAgICAvLyBUT0RPKGFuZHlzb3RvKTpcbiAgICAgICAgLy8gYXNzZXJ0KHRoaXMuc3RhdGVfID09PSBJbnRlcm5hbFRhc2tTdGF0ZS5SVU5OSU5HIHx8XG4gICAgICAgIC8vICAgICAgICB0aGlzLnN0YXRlXyA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0lORyB8fFxuICAgICAgICAvLyAgICAgICAgdGhpcy5zdGF0ZV8gPT09IEludGVybmFsVGFza1N0YXRlLkNBTkNFTElORyk7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gc3RhdGU7XG4gICAgICAgIHRoaXMuX25vdGlmeU9ic2VydmVycygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuU1VDQ0VTUzpcbiAgICAgICAgLy8gVE9ETyhhbmR5c290byk6XG4gICAgICAgIC8vIGFzc2VydCh0aGlzLnN0YXRlXyA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUlVOTklORyB8fFxuICAgICAgICAvLyAgICAgICAgdGhpcy5zdGF0ZV8gPT09IEludGVybmFsVGFza1N0YXRlLlBBVVNJTkcgfHxcbiAgICAgICAgLy8gICAgICAgIHRoaXMuc3RhdGVfID09PSBJbnRlcm5hbFRhc2tTdGF0ZS5DQU5DRUxJTkcpO1xuICAgICAgICB0aGlzLl9zdGF0ZSA9IHN0YXRlO1xuICAgICAgICB0aGlzLl9ub3RpZnlPYnNlcnZlcnMoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OiAvLyBJZ25vcmVcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNvbXBsZXRlVHJhbnNpdGlvbnNfKCk6IHZvaWQge1xuICAgIHN3aXRjaCAodGhpcy5fc3RhdGUpIHtcbiAgICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0lORzpcbiAgICAgICAgdGhpcy5fdHJhbnNpdGlvbihJbnRlcm5hbFRhc2tTdGF0ZS5QQVVTRUQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgSW50ZXJuYWxUYXNrU3RhdGUuQ0FOQ0VMSU5HOlxuICAgICAgICB0aGlzLl90cmFuc2l0aW9uKEludGVybmFsVGFza1N0YXRlLkNBTkNFTEVEKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEludGVybmFsVGFza1N0YXRlLlJVTk5JTkc6XG4gICAgICAgIHRoaXMuX3N0YXJ0KCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gVE9ETyhhbmR5c290byk6IGFzc2VydChmYWxzZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNuYXBzaG90IG9mIHRoZSBjdXJyZW50IHRhc2sgc3RhdGUuXG4gICAqL1xuICBnZXQgc25hcHNob3QoKTogVXBsb2FkVGFza1NuYXBzaG90IHtcbiAgICBjb25zdCBleHRlcm5hbFN0YXRlID0gdGFza1N0YXRlRnJvbUludGVybmFsVGFza1N0YXRlKHRoaXMuX3N0YXRlKTtcbiAgICByZXR1cm4ge1xuICAgICAgYnl0ZXNUcmFuc2ZlcnJlZDogdGhpcy5fdHJhbnNmZXJyZWQsXG4gICAgICB0b3RhbEJ5dGVzOiB0aGlzLl9ibG9iLnNpemUoKSxcbiAgICAgIHN0YXRlOiBleHRlcm5hbFN0YXRlLFxuICAgICAgbWV0YWRhdGE6IHRoaXMuX21ldGFkYXRhISxcbiAgICAgIHRhc2s6IHRoaXMsXG4gICAgICByZWY6IHRoaXMuX3JlZlxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGNhbGxiYWNrIGZvciBhbiBldmVudC5cbiAgICogQHBhcmFtIHR5cGUgLSBUaGUgdHlwZSBvZiBldmVudCB0byBsaXN0ZW4gZm9yLlxuICAgKiBAcGFyYW0gbmV4dE9yT2JzZXJ2ZXIgLVxuICAgKiAgICAgVGhlIGBuZXh0YCBmdW5jdGlvbiwgd2hpY2ggZ2V0cyBjYWxsZWQgZm9yIGVhY2ggaXRlbSBpblxuICAgKiAgICAgdGhlIGV2ZW50IHN0cmVhbSwgb3IgYW4gb2JzZXJ2ZXIgb2JqZWN0IHdpdGggc29tZSBvciBhbGwgb2YgdGhlc2UgdGhyZWVcbiAgICogICAgIHByb3BlcnRpZXMgKGBuZXh0YCwgYGVycm9yYCwgYGNvbXBsZXRlYCkuXG4gICAqIEBwYXJhbSBlcnJvciAtIEEgZnVuY3Rpb24gdGhhdCBnZXRzIGNhbGxlZCB3aXRoIGEgYFN0b3JhZ2VFcnJvcmBcbiAgICogICAgIGlmIHRoZSBldmVudCBzdHJlYW0gZW5kcyBkdWUgdG8gYW4gZXJyb3IuXG4gICAqIEBwYXJhbSBjb21wbGV0ZWQgLSBBIGZ1bmN0aW9uIHRoYXQgZ2V0cyBjYWxsZWQgaWYgdGhlXG4gICAqICAgICBldmVudCBzdHJlYW0gZW5kcyBub3JtYWxseS5cbiAgICogQHJldHVybnNcbiAgICogICAgIElmIG9ubHkgdGhlIGV2ZW50IGFyZ3VtZW50IGlzIHBhc3NlZCwgcmV0dXJucyBhIGZ1bmN0aW9uIHlvdSBjYW4gdXNlIHRvXG4gICAqICAgICBhZGQgY2FsbGJhY2tzIChzZWUgdGhlIGV4YW1wbGVzIGFib3ZlKS4gSWYgbW9yZSB0aGFuIGp1c3QgdGhlIGV2ZW50XG4gICAqICAgICBhcmd1bWVudCBpcyBwYXNzZWQsIHJldHVybnMgYSBmdW5jdGlvbiB5b3UgY2FuIGNhbGwgdG8gdW5yZWdpc3RlciB0aGVcbiAgICogICAgIGNhbGxiYWNrcy5cbiAgICovXG4gIG9uKFxuICAgIHR5cGU6IFRhc2tFdmVudCxcbiAgICBuZXh0T3JPYnNlcnZlcj86XG4gICAgICB8IFN0b3JhZ2VPYnNlcnZlcjxVcGxvYWRUYXNrU25hcHNob3Q+XG4gICAgICB8IG51bGxcbiAgICAgIHwgKChzbmFwc2hvdDogVXBsb2FkVGFza1NuYXBzaG90KSA9PiB1bmtub3duKSxcbiAgICBlcnJvcj86ICgoYTogU3RvcmFnZUVycm9yKSA9PiB1bmtub3duKSB8IG51bGwsXG4gICAgY29tcGxldGVkPzogQ29tcGxldGVGbiB8IG51bGxcbiAgKTogVW5zdWJzY3JpYmUgfCBTdWJzY3JpYmU8VXBsb2FkVGFza1NuYXBzaG90PiB7XG4gICAgLy8gTm90ZTogYHR5cGVgIGlzbid0IGJlaW5nIHVzZWQuIEl0cyB0eXBlIGlzIGFsc28gaW5jb3JyZWN0LiBUYXNrRXZlbnQgc2hvdWxkIG5vdCBiZSBhIHN0cmluZy5cbiAgICBjb25zdCBvYnNlcnZlciA9IG5ldyBPYnNlcnZlcihcbiAgICAgIChuZXh0T3JPYnNlcnZlciBhc1xuICAgICAgICB8IFN0b3JhZ2VPYnNlcnZlckludGVybmFsPFVwbG9hZFRhc2tTbmFwc2hvdD5cbiAgICAgICAgfCBOZXh0Rm48VXBsb2FkVGFza1NuYXBzaG90PikgfHwgdW5kZWZpbmVkLFxuICAgICAgZXJyb3IgfHwgdW5kZWZpbmVkLFxuICAgICAgY29tcGxldGVkIHx8IHVuZGVmaW5lZFxuICAgICk7XG4gICAgdGhpcy5fYWRkT2JzZXJ2ZXIob2JzZXJ2ZXIpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB0aGlzLl9yZW1vdmVPYnNlcnZlcihvYnNlcnZlcik7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG9iamVjdCBiZWhhdmVzIGxpa2UgYSBQcm9taXNlLCBhbmQgcmVzb2x2ZXMgd2l0aCBpdHMgc25hcHNob3QgZGF0YVxuICAgKiB3aGVuIHRoZSB1cGxvYWQgY29tcGxldGVzLlxuICAgKiBAcGFyYW0gb25GdWxmaWxsZWQgLSBUaGUgZnVsZmlsbG1lbnQgY2FsbGJhY2suIFByb21pc2UgY2hhaW5pbmcgd29ya3MgYXMgbm9ybWFsLlxuICAgKiBAcGFyYW0gb25SZWplY3RlZCAtIFRoZSByZWplY3Rpb24gY2FsbGJhY2suXG4gICAqL1xuICB0aGVuPFU+KFxuICAgIG9uRnVsZmlsbGVkPzogKCh2YWx1ZTogVXBsb2FkVGFza1NuYXBzaG90KSA9PiBVIHwgUHJvbWlzZTxVPikgfCBudWxsLFxuICAgIG9uUmVqZWN0ZWQ/OiAoKGVycm9yOiBTdG9yYWdlRXJyb3IpID0+IFUgfCBQcm9taXNlPFU+KSB8IG51bGxcbiAgKTogUHJvbWlzZTxVPiB7XG4gICAgLy8gVGhlc2UgY2FzdHMgYXJlIG5lZWRlZCBzbyB0aGF0IFR5cGVTY3JpcHQgY2FuIGluZmVyIHRoZSB0eXBlcyBvZiB0aGVcbiAgICAvLyByZXN1bHRpbmcgUHJvbWlzZS5cbiAgICByZXR1cm4gdGhpcy5fcHJvbWlzZS50aGVuPFU+KFxuICAgICAgb25GdWxmaWxsZWQgYXMgKHZhbHVlOiBVcGxvYWRUYXNrU25hcHNob3QpID0+IFUgfCBQcm9taXNlPFU+LFxuICAgICAgb25SZWplY3RlZCBhcyAoKGVycm9yOiB1bmtub3duKSA9PiBQcm9taXNlPG5ldmVyPikgfCBudWxsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFcXVpdmFsZW50IHRvIGNhbGxpbmcgYHRoZW4obnVsbCwgb25SZWplY3RlZClgLlxuICAgKi9cbiAgY2F0Y2g8VD4ob25SZWplY3RlZDogKHAxOiBTdG9yYWdlRXJyb3IpID0+IFQgfCBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgcmV0dXJuIHRoaXMudGhlbihudWxsLCBvblJlamVjdGVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIHRoZSBnaXZlbiBvYnNlcnZlci5cbiAgICovXG4gIHByaXZhdGUgX2FkZE9ic2VydmVyKG9ic2VydmVyOiBPYnNlcnZlcjxVcGxvYWRUYXNrU25hcHNob3Q+KTogdm9pZCB7XG4gICAgdGhpcy5fb2JzZXJ2ZXJzLnB1c2gob2JzZXJ2ZXIpO1xuICAgIHRoaXMuX25vdGlmeU9ic2VydmVyKG9ic2VydmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIHRoZSBnaXZlbiBvYnNlcnZlci5cbiAgICovXG4gIHByaXZhdGUgX3JlbW92ZU9ic2VydmVyKG9ic2VydmVyOiBPYnNlcnZlcjxVcGxvYWRUYXNrU25hcHNob3Q+KTogdm9pZCB7XG4gICAgY29uc3QgaSA9IHRoaXMuX29ic2VydmVycy5pbmRleE9mKG9ic2VydmVyKTtcbiAgICBpZiAoaSAhPT0gLTEpIHtcbiAgICAgIHRoaXMuX29ic2VydmVycy5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfbm90aWZ5T2JzZXJ2ZXJzKCk6IHZvaWQge1xuICAgIHRoaXMuX2ZpbmlzaFByb21pc2UoKTtcbiAgICBjb25zdCBvYnNlcnZlcnMgPSB0aGlzLl9vYnNlcnZlcnMuc2xpY2UoKTtcbiAgICBvYnNlcnZlcnMuZm9yRWFjaChvYnNlcnZlciA9PiB7XG4gICAgICB0aGlzLl9ub3RpZnlPYnNlcnZlcihvYnNlcnZlcik7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9maW5pc2hQcm9taXNlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9yZXNvbHZlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGxldCB0cmlnZ2VyZWQgPSB0cnVlO1xuICAgICAgc3dpdGNoICh0YXNrU3RhdGVGcm9tSW50ZXJuYWxUYXNrU3RhdGUodGhpcy5fc3RhdGUpKSB7XG4gICAgICAgIGNhc2UgVGFza1N0YXRlLlNVQ0NFU1M6XG4gICAgICAgICAgZmJzQXN5bmModGhpcy5fcmVzb2x2ZS5iaW5kKG51bGwsIHRoaXMuc25hcHNob3QpKSgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRhc2tTdGF0ZS5DQU5DRUxFRDpcbiAgICAgICAgY2FzZSBUYXNrU3RhdGUuRVJST1I6XG4gICAgICAgICAgY29uc3QgdG9DYWxsID0gdGhpcy5fcmVqZWN0IGFzIChwMTogU3RvcmFnZUVycm9yKSA9PiB2b2lkO1xuICAgICAgICAgIGZic0FzeW5jKHRvQ2FsbC5iaW5kKG51bGwsIHRoaXMuX2Vycm9yIGFzIFN0b3JhZ2VFcnJvcikpKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdHJpZ2dlcmVkID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAodHJpZ2dlcmVkKSB7XG4gICAgICAgIHRoaXMuX3Jlc29sdmUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuX3JlamVjdCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9ub3RpZnlPYnNlcnZlcihvYnNlcnZlcjogT2JzZXJ2ZXI8VXBsb2FkVGFza1NuYXBzaG90Pik6IHZvaWQge1xuICAgIGNvbnN0IGV4dGVybmFsU3RhdGUgPSB0YXNrU3RhdGVGcm9tSW50ZXJuYWxUYXNrU3RhdGUodGhpcy5fc3RhdGUpO1xuICAgIHN3aXRjaCAoZXh0ZXJuYWxTdGF0ZSkge1xuICAgICAgY2FzZSBUYXNrU3RhdGUuUlVOTklORzpcbiAgICAgIGNhc2UgVGFza1N0YXRlLlBBVVNFRDpcbiAgICAgICAgaWYgKG9ic2VydmVyLm5leHQpIHtcbiAgICAgICAgICBmYnNBc3luYyhvYnNlcnZlci5uZXh0LmJpbmQob2JzZXJ2ZXIsIHRoaXMuc25hcHNob3QpKSgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUYXNrU3RhdGUuU1VDQ0VTUzpcbiAgICAgICAgaWYgKG9ic2VydmVyLmNvbXBsZXRlKSB7XG4gICAgICAgICAgZmJzQXN5bmMob2JzZXJ2ZXIuY29tcGxldGUuYmluZChvYnNlcnZlcikpKCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRhc2tTdGF0ZS5DQU5DRUxFRDpcbiAgICAgIGNhc2UgVGFza1N0YXRlLkVSUk9SOlxuICAgICAgICBpZiAob2JzZXJ2ZXIuZXJyb3IpIHtcbiAgICAgICAgICBmYnNBc3luYyhcbiAgICAgICAgICAgIG9ic2VydmVyLmVycm9yLmJpbmQob2JzZXJ2ZXIsIHRoaXMuX2Vycm9yIGFzIFN0b3JhZ2VFcnJvcilcbiAgICAgICAgICApKCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBUT0RPKGFuZHlzb3RvKTogYXNzZXJ0KGZhbHNlKTtcbiAgICAgICAgaWYgKG9ic2VydmVyLmVycm9yKSB7XG4gICAgICAgICAgZmJzQXN5bmMoXG4gICAgICAgICAgICBvYnNlcnZlci5lcnJvci5iaW5kKG9ic2VydmVyLCB0aGlzLl9lcnJvciBhcyBTdG9yYWdlRXJyb3IpXG4gICAgICAgICAgKSgpO1xuICAgICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc3VtZXMgYSBwYXVzZWQgdGFzay4gSGFzIG5vIGVmZmVjdCBvbiBhIGN1cnJlbnRseSBydW5uaW5nIG9yIGZhaWxlZCB0YXNrLlxuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBvcGVyYXRpb24gdG9vayBlZmZlY3QsIGZhbHNlIGlmIGlnbm9yZWQuXG4gICAqL1xuICByZXN1bWUoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdmFsaWQgPVxuICAgICAgdGhpcy5fc3RhdGUgPT09IEludGVybmFsVGFza1N0YXRlLlBBVVNFRCB8fFxuICAgICAgdGhpcy5fc3RhdGUgPT09IEludGVybmFsVGFza1N0YXRlLlBBVVNJTkc7XG4gICAgaWYgKHZhbGlkKSB7XG4gICAgICB0aGlzLl90cmFuc2l0aW9uKEludGVybmFsVGFza1N0YXRlLlJVTk5JTkcpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsaWQ7XG4gIH1cblxuICAvKipcbiAgICogUGF1c2VzIGEgY3VycmVudGx5IHJ1bm5pbmcgdGFzay4gSGFzIG5vIGVmZmVjdCBvbiBhIHBhdXNlZCBvciBmYWlsZWQgdGFzay5cbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgb3BlcmF0aW9uIHRvb2sgZWZmZWN0LCBmYWxzZSBpZiBpZ25vcmVkLlxuICAgKi9cbiAgcGF1c2UoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdmFsaWQgPSB0aGlzLl9zdGF0ZSA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUlVOTklORztcbiAgICBpZiAodmFsaWQpIHtcbiAgICAgIHRoaXMuX3RyYW5zaXRpb24oSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0lORyk7XG4gICAgfVxuICAgIHJldHVybiB2YWxpZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYW5jZWxzIGEgY3VycmVudGx5IHJ1bm5pbmcgb3IgcGF1c2VkIHRhc2suIEhhcyBubyBlZmZlY3Qgb24gYSBjb21wbGV0ZSBvclxuICAgKiBmYWlsZWQgdGFzay5cbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgb3BlcmF0aW9uIHRvb2sgZWZmZWN0LCBmYWxzZSBpZiBpZ25vcmVkLlxuICAgKi9cbiAgY2FuY2VsKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHZhbGlkID1cbiAgICAgIHRoaXMuX3N0YXRlID09PSBJbnRlcm5hbFRhc2tTdGF0ZS5SVU5OSU5HIHx8XG4gICAgICB0aGlzLl9zdGF0ZSA9PT0gSW50ZXJuYWxUYXNrU3RhdGUuUEFVU0lORztcbiAgICBpZiAodmFsaWQpIHtcbiAgICAgIHRoaXMuX3RyYW5zaXRpb24oSW50ZXJuYWxUYXNrU3RhdGUuQ0FOQ0VMSU5HKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbGlkO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IERlZmluZXMgdGhlIEZpcmViYXNlIFN0b3JhZ2VSZWZlcmVuY2UgY2xhc3MuXG4gKi9cblxuaW1wb3J0IHsgRmJzQmxvYiB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vYmxvYic7XG5pbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vbG9jYXRpb24nO1xuaW1wb3J0IHsgZ2V0TWFwcGluZ3MgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL21ldGFkYXRhJztcbmltcG9ydCB7IGNoaWxkLCBsYXN0Q29tcG9uZW50LCBwYXJlbnQgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3BhdGgnO1xuaW1wb3J0IHtcbiAgZGVsZXRlT2JqZWN0IGFzIHJlcXVlc3RzRGVsZXRlT2JqZWN0LFxuICBnZXRCeXRlcyxcbiAgZ2V0RG93bmxvYWRVcmwgYXMgcmVxdWVzdHNHZXREb3dubG9hZFVybCxcbiAgZ2V0TWV0YWRhdGEgYXMgcmVxdWVzdHNHZXRNZXRhZGF0YSxcbiAgbGlzdCBhcyByZXF1ZXN0c0xpc3QsXG4gIG11bHRpcGFydFVwbG9hZCxcbiAgdXBkYXRlTWV0YWRhdGEgYXMgcmVxdWVzdHNVcGRhdGVNZXRhZGF0YVxufSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3JlcXVlc3RzJztcbmltcG9ydCB7IExpc3RPcHRpb25zLCBVcGxvYWRSZXN1bHQgfSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBkYXRhRnJvbVN0cmluZywgU3RyaW5nRm9ybWF0IH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi9zdHJpbmcnO1xuaW1wb3J0IHsgTWV0YWRhdGEgfSBmcm9tICcuL21ldGFkYXRhJztcbmltcG9ydCB7IEZpcmViYXNlU3RvcmFnZUltcGwgfSBmcm9tICcuL3NlcnZpY2UnO1xuaW1wb3J0IHsgTGlzdFJlc3VsdCB9IGZyb20gJy4vbGlzdCc7XG5pbXBvcnQgeyBVcGxvYWRUYXNrIH0gZnJvbSAnLi90YXNrJztcbmltcG9ydCB7IGludmFsaWRSb290T3BlcmF0aW9uLCBub0Rvd25sb2FkVVJMIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi9lcnJvcic7XG5pbXBvcnQgeyB2YWxpZGF0ZU51bWJlciB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vdHlwZSc7XG5pbXBvcnQge1xuICBuZXdCbG9iQ29ubmVjdGlvbixcbiAgbmV3Qnl0ZXNDb25uZWN0aW9uLFxuICBuZXdTdHJlYW1Db25uZWN0aW9uLFxuICBuZXdUZXh0Q29ubmVjdGlvblxufSBmcm9tICcuL3BsYXRmb3JtL2Nvbm5lY3Rpb24nO1xuaW1wb3J0IHsgUmVxdWVzdEluZm8gfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3JlcXVlc3RpbmZvJztcblxuLyoqXG4gKiBQcm92aWRlcyBtZXRob2RzIHRvIGludGVyYWN0IHdpdGggYSBidWNrZXQgaW4gdGhlIEZpcmViYXNlIFN0b3JhZ2Ugc2VydmljZS5cbiAqIEBpbnRlcm5hbFxuICogQHBhcmFtIF9sb2NhdGlvbiAtIEFuIGZicy5sb2NhdGlvbiwgb3IgdGhlIFVSTCBhdFxuICogICAgIHdoaWNoIHRvIGJhc2UgdGhpcyBvYmplY3QsIGluIG9uZSBvZiB0aGUgZm9sbG93aW5nIGZvcm1zOlxuICogICAgICAgICBnczovLzxidWNrZXQ+LzxvYmplY3QtcGF0aD5cbiAqICAgICAgICAgaHR0cFtzXTovL2ZpcmViYXNlc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9cbiAqICAgICAgICAgICAgICAgICAgICAgPGFwaS12ZXJzaW9uPi9iLzxidWNrZXQ+L28vPG9iamVjdC1wYXRoPlxuICogICAgIEFueSBxdWVyeSBvciBmcmFnbWVudCBzdHJpbmdzIHdpbGwgYmUgaWdub3JlZCBpbiB0aGUgaHR0cFtzXVxuICogICAgIGZvcm1hdC4gSWYgbm8gdmFsdWUgaXMgcGFzc2VkLCB0aGUgc3RvcmFnZSBvYmplY3Qgd2lsbCB1c2UgYSBVUkwgYmFzZWQgb25cbiAqICAgICB0aGUgcHJvamVjdCBJRCBvZiB0aGUgYmFzZSBmaXJlYmFzZS5BcHAgaW5zdGFuY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWZlcmVuY2Uge1xuICBfbG9jYXRpb246IExvY2F0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX3NlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gICAgbG9jYXRpb246IHN0cmluZyB8IExvY2F0aW9uXG4gICkge1xuICAgIGlmIChsb2NhdGlvbiBpbnN0YW5jZW9mIExvY2F0aW9uKSB7XG4gICAgICB0aGlzLl9sb2NhdGlvbiA9IGxvY2F0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9sb2NhdGlvbiA9IExvY2F0aW9uLm1ha2VGcm9tVXJsKGxvY2F0aW9uLCBfc2VydmljZS5ob3N0KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgVVJMIGZvciB0aGUgYnVja2V0IGFuZCBwYXRoIHRoaXMgb2JqZWN0IHJlZmVyZW5jZXMsXG4gICAqICAgICBpbiB0aGUgZm9ybSBnczovLzxidWNrZXQ+LzxvYmplY3QtcGF0aD5cbiAgICogQG92ZXJyaWRlXG4gICAqL1xuICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiAnZ3M6Ly8nICsgdGhpcy5fbG9jYXRpb24uYnVja2V0ICsgJy8nICsgdGhpcy5fbG9jYXRpb24ucGF0aDtcbiAgfVxuXG4gIHByb3RlY3RlZCBfbmV3UmVmKFxuICAgIHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsXG4gICAgbG9jYXRpb246IExvY2F0aW9uXG4gICk6IFJlZmVyZW5jZSB7XG4gICAgcmV0dXJuIG5ldyBSZWZlcmVuY2Uoc2VydmljZSwgbG9jYXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgcmVmZXJlbmNlIHRvIHRoZSByb290IG9mIHRoaXMgb2JqZWN0J3MgYnVja2V0LlxuICAgKi9cbiAgZ2V0IHJvb3QoKTogUmVmZXJlbmNlIHtcbiAgICBjb25zdCBsb2NhdGlvbiA9IG5ldyBMb2NhdGlvbih0aGlzLl9sb2NhdGlvbi5idWNrZXQsICcnKTtcbiAgICByZXR1cm4gdGhpcy5fbmV3UmVmKHRoaXMuX3NlcnZpY2UsIGxvY2F0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYnVja2V0IGNvbnRhaW5pbmcgdGhpcyByZWZlcmVuY2UncyBvYmplY3QuXG4gICAqL1xuICBnZXQgYnVja2V0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2xvY2F0aW9uLmJ1Y2tldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgZnVsbCBwYXRoIG9mIHRoaXMgb2JqZWN0LlxuICAgKi9cbiAgZ2V0IGZ1bGxQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2xvY2F0aW9uLnBhdGg7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHNob3J0IG5hbWUgb2YgdGhpcyBvYmplY3QsIHdoaWNoIGlzIHRoZSBsYXN0IGNvbXBvbmVudCBvZiB0aGUgZnVsbCBwYXRoLlxuICAgKiBGb3IgZXhhbXBsZSwgaWYgZnVsbFBhdGggaXMgJ2Z1bGwvcGF0aC9pbWFnZS5wbmcnLCBuYW1lIGlzICdpbWFnZS5wbmcnLlxuICAgKi9cbiAgZ2V0IG5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbGFzdENvbXBvbmVudCh0aGlzLl9sb2NhdGlvbi5wYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYFN0b3JhZ2VTZXJ2aWNlYCBpbnN0YW5jZSB0aGlzIGBTdG9yYWdlUmVmZXJlbmNlYCBpcyBhc3NvY2lhdGVkIHdpdGguXG4gICAqL1xuICBnZXQgc3RvcmFnZSgpOiBGaXJlYmFzZVN0b3JhZ2VJbXBsIHtcbiAgICByZXR1cm4gdGhpcy5fc2VydmljZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGBTdG9yYWdlUmVmZXJlbmNlYCBwb2ludGluZyB0byB0aGUgcGFyZW50IGxvY2F0aW9uIG9mIHRoaXMgYFN0b3JhZ2VSZWZlcmVuY2VgLCBvciBudWxsIGlmXG4gICAqIHRoaXMgcmVmZXJlbmNlIGlzIHRoZSByb290LlxuICAgKi9cbiAgZ2V0IHBhcmVudCgpOiBSZWZlcmVuY2UgfCBudWxsIHtcbiAgICBjb25zdCBuZXdQYXRoID0gcGFyZW50KHRoaXMuX2xvY2F0aW9uLnBhdGgpO1xuICAgIGlmIChuZXdQYXRoID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgbG9jYXRpb24gPSBuZXcgTG9jYXRpb24odGhpcy5fbG9jYXRpb24uYnVja2V0LCBuZXdQYXRoKTtcbiAgICByZXR1cm4gbmV3IFJlZmVyZW5jZSh0aGlzLl9zZXJ2aWNlLCBsb2NhdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogVXRpbGl0eSBmdW5jdGlvbiB0byB0aHJvdyBhbiBlcnJvciBpbiBtZXRob2RzIHRoYXQgZG8gbm90IGFjY2VwdCBhIHJvb3QgcmVmZXJlbmNlLlxuICAgKi9cbiAgX3Rocm93SWZSb290KG5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9sb2NhdGlvbi5wYXRoID09PSAnJykge1xuICAgICAgdGhyb3cgaW52YWxpZFJvb3RPcGVyYXRpb24obmFtZSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogRG93bmxvYWQgdGhlIGJ5dGVzIGF0IHRoZSBvYmplY3QncyBsb2NhdGlvbi5cbiAqIEByZXR1cm5zIEEgUHJvbWlzZSBjb250YWluaW5nIHRoZSBkb3dubG9hZGVkIGJ5dGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Qnl0ZXNJbnRlcm5hbChcbiAgcmVmOiBSZWZlcmVuY2UsXG4gIG1heERvd25sb2FkU2l6ZUJ5dGVzPzogbnVtYmVyXG4pOiBQcm9taXNlPEFycmF5QnVmZmVyPiB7XG4gIHJlZi5fdGhyb3dJZlJvb3QoJ2dldEJ5dGVzJyk7XG4gIGNvbnN0IHJlcXVlc3RJbmZvID0gZ2V0Qnl0ZXMoXG4gICAgcmVmLnN0b3JhZ2UsXG4gICAgcmVmLl9sb2NhdGlvbixcbiAgICBtYXhEb3dubG9hZFNpemVCeXRlc1xuICApO1xuICByZXR1cm4gcmVmLnN0b3JhZ2VcbiAgICAubWFrZVJlcXVlc3RXaXRoVG9rZW5zKHJlcXVlc3RJbmZvLCBuZXdCeXRlc0Nvbm5lY3Rpb24pXG4gICAgLnRoZW4oYnl0ZXMgPT5cbiAgICAgIG1heERvd25sb2FkU2l6ZUJ5dGVzICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyAvLyBHQ1MgbWF5IG5vdCBob25vciB0aGUgUmFuZ2UgaGVhZGVyIGZvciBzbWFsbCBmaWxlc1xuICAgICAgICAgIChieXRlcyBhcyBBcnJheUJ1ZmZlcikuc2xpY2UoMCwgbWF4RG93bmxvYWRTaXplQnl0ZXMpXG4gICAgICAgIDogKGJ5dGVzIGFzIEFycmF5QnVmZmVyKVxuICAgICk7XG59XG5cbi8qKlxuICogRG93bmxvYWQgdGhlIGJ5dGVzIGF0IHRoZSBvYmplY3QncyBsb2NhdGlvbi5cbiAqIEByZXR1cm5zIEEgUHJvbWlzZSBjb250YWluaW5nIHRoZSBkb3dubG9hZGVkIGJsb2IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRCbG9iSW50ZXJuYWwoXG4gIHJlZjogUmVmZXJlbmNlLFxuICBtYXhEb3dubG9hZFNpemVCeXRlcz86IG51bWJlclxuKTogUHJvbWlzZTxCbG9iPiB7XG4gIHJlZi5fdGhyb3dJZlJvb3QoJ2dldEJsb2InKTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSBnZXRCeXRlcyhcbiAgICByZWYuc3RvcmFnZSxcbiAgICByZWYuX2xvY2F0aW9uLFxuICAgIG1heERvd25sb2FkU2l6ZUJ5dGVzXG4gICk7XG4gIHJldHVybiByZWYuc3RvcmFnZVxuICAgIC5tYWtlUmVxdWVzdFdpdGhUb2tlbnMocmVxdWVzdEluZm8sIG5ld0Jsb2JDb25uZWN0aW9uKVxuICAgIC50aGVuKGJsb2IgPT5cbiAgICAgIG1heERvd25sb2FkU2l6ZUJ5dGVzICE9PSB1bmRlZmluZWRcbiAgICAgICAgPyAvLyBHQ1MgbWF5IG5vdCBob25vciB0aGUgUmFuZ2UgaGVhZGVyIGZvciBzbWFsbCBmaWxlc1xuICAgICAgICAgIChibG9iIGFzIEJsb2IpLnNsaWNlKDAsIG1heERvd25sb2FkU2l6ZUJ5dGVzKVxuICAgICAgICA6IChibG9iIGFzIEJsb2IpXG4gICAgKTtcbn1cblxuLyoqIFN0cmVhbSB0aGUgYnl0ZXMgYXQgdGhlIG9iamVjdCdzIGxvY2F0aW9uLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0cmVhbUludGVybmFsKFxuICByZWY6IFJlZmVyZW5jZSxcbiAgbWF4RG93bmxvYWRTaXplQnl0ZXM/OiBudW1iZXJcbik6IFJlYWRhYmxlU3RyZWFtIHtcbiAgcmVmLl90aHJvd0lmUm9vdCgnZ2V0U3RyZWFtJyk7XG4gIGNvbnN0IHJlcXVlc3RJbmZvOiBSZXF1ZXN0SW5mbzxSZWFkYWJsZVN0cmVhbSwgUmVhZGFibGVTdHJlYW0+ID0gZ2V0Qnl0ZXMoXG4gICAgcmVmLnN0b3JhZ2UsXG4gICAgcmVmLl9sb2NhdGlvbixcbiAgICBtYXhEb3dubG9hZFNpemVCeXRlc1xuICApO1xuXG4gIC8vIFRyYW5zZm9ybXMgdGhlIHN0cmVhbSBzbyB0aGF0IG9ubHkgYG1heERvd25sb2FkU2l6ZUJ5dGVzYCBieXRlcyBhcmUgcGlwZWQgdG8gdGhlIHJlc3VsdFxuICBjb25zdCBuZXdNYXhTaXplVHJhbnNmb3JtID0gKG46IG51bWJlcik6IFRyYW5zZm9ybWVyID0+IHtcbiAgICBsZXQgbWlzc2luZ0J5dGVzID0gbjtcbiAgICByZXR1cm4ge1xuICAgICAgdHJhbnNmb3JtKGNodW5rLCBjb250cm9sbGVyOiBUcmFuc2Zvcm1TdHJlYW1EZWZhdWx0Q29udHJvbGxlcikge1xuICAgICAgICAvLyBHQ1MgbWF5IG5vdCBob25vciB0aGUgUmFuZ2UgaGVhZGVyIGZvciBzbWFsbCBmaWxlc1xuICAgICAgICBpZiAoY2h1bmsubGVuZ3RoIDwgbWlzc2luZ0J5dGVzKSB7XG4gICAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGNodW5rKTtcbiAgICAgICAgICBtaXNzaW5nQnl0ZXMgLT0gY2h1bmsubGVuZ3RoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZShjaHVuay5zbGljZSgwLCBtaXNzaW5nQnl0ZXMpKTtcbiAgICAgICAgICBjb250cm9sbGVyLnRlcm1pbmF0ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICBjb25zdCByZXN1bHQgPVxuICAgIG1heERvd25sb2FkU2l6ZUJ5dGVzICE9PSB1bmRlZmluZWRcbiAgICAgID8gbmV3IFRyYW5zZm9ybVN0cmVhbShuZXdNYXhTaXplVHJhbnNmb3JtKG1heERvd25sb2FkU2l6ZUJ5dGVzKSlcbiAgICAgIDogbmV3IFRyYW5zZm9ybVN0cmVhbSgpOyAvLyBUaGUgZGVmYXVsdCB0cmFuc2Zvcm1lciBmb3J3YXJkcyBhbGwgY2h1bmtzIHRvIGl0cyByZWFkYWJsZSBzaWRlXG5cbiAgcmVmLnN0b3JhZ2VcbiAgICAubWFrZVJlcXVlc3RXaXRoVG9rZW5zKHJlcXVlc3RJbmZvLCBuZXdTdHJlYW1Db25uZWN0aW9uKVxuICAgIC50aGVuKHJlYWRhYmxlU3RyZWFtID0+IHJlYWRhYmxlU3RyZWFtLnBpcGVUaHJvdWdoKHJlc3VsdCkpXG4gICAgLmNhdGNoKGVyciA9PiByZXN1bHQud3JpdGFibGUuYWJvcnQoZXJyKSk7XG5cbiAgcmV0dXJuIHJlc3VsdC5yZWFkYWJsZTtcbn1cblxuLyoqXG4gKiBVcGxvYWRzIGRhdGEgdG8gdGhpcyBvYmplY3QncyBsb2NhdGlvbi5cbiAqIFRoZSB1cGxvYWQgaXMgbm90IHJlc3VtYWJsZS5cbiAqXG4gKiBAcGFyYW0gcmVmIC0gU3RvcmFnZVJlZmVyZW5jZSB3aGVyZSBkYXRhIHNob3VsZCBiZSB1cGxvYWRlZC5cbiAqIEBwYXJhbSBkYXRhIC0gVGhlIGRhdGEgdG8gdXBsb2FkLlxuICogQHBhcmFtIG1ldGFkYXRhIC0gTWV0YWRhdGEgZm9yIHRoZSBuZXdseSB1cGxvYWRlZCBkYXRhLlxuICogQHJldHVybnMgQSBQcm9taXNlIGNvbnRhaW5pbmcgYW4gVXBsb2FkUmVzdWx0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGxvYWRCeXRlcyhcbiAgcmVmOiBSZWZlcmVuY2UsXG4gIGRhdGE6IEJsb2IgfCBVaW50OEFycmF5IHwgQXJyYXlCdWZmZXIsXG4gIG1ldGFkYXRhPzogTWV0YWRhdGFcbik6IFByb21pc2U8VXBsb2FkUmVzdWx0PiB7XG4gIHJlZi5fdGhyb3dJZlJvb3QoJ3VwbG9hZEJ5dGVzJyk7XG4gIGNvbnN0IHJlcXVlc3RJbmZvID0gbXVsdGlwYXJ0VXBsb2FkKFxuICAgIHJlZi5zdG9yYWdlLFxuICAgIHJlZi5fbG9jYXRpb24sXG4gICAgZ2V0TWFwcGluZ3MoKSxcbiAgICBuZXcgRmJzQmxvYihkYXRhLCB0cnVlKSxcbiAgICBtZXRhZGF0YVxuICApO1xuICByZXR1cm4gcmVmLnN0b3JhZ2VcbiAgICAubWFrZVJlcXVlc3RXaXRoVG9rZW5zKHJlcXVlc3RJbmZvLCBuZXdUZXh0Q29ubmVjdGlvbilcbiAgICAudGhlbihmaW5hbE1ldGFkYXRhID0+IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1ldGFkYXRhOiBmaW5hbE1ldGFkYXRhLFxuICAgICAgICByZWZcbiAgICAgIH07XG4gICAgfSk7XG59XG5cbi8qKlxuICogVXBsb2FkcyBkYXRhIHRvIHRoaXMgb2JqZWN0J3MgbG9jYXRpb24uXG4gKiBUaGUgdXBsb2FkIGNhbiBiZSBwYXVzZWQgYW5kIHJlc3VtZWQsIGFuZCBleHBvc2VzIHByb2dyZXNzIHVwZGF0ZXMuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0gU3RvcmFnZVJlZmVyZW5jZSB3aGVyZSBkYXRhIHNob3VsZCBiZSB1cGxvYWRlZC5cbiAqIEBwYXJhbSBkYXRhIC0gVGhlIGRhdGEgdG8gdXBsb2FkLlxuICogQHBhcmFtIG1ldGFkYXRhIC0gTWV0YWRhdGEgZm9yIHRoZSBuZXdseSB1cGxvYWRlZCBkYXRhLlxuICogQHJldHVybnMgQW4gVXBsb2FkVGFza1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXBsb2FkQnl0ZXNSZXN1bWFibGUoXG4gIHJlZjogUmVmZXJlbmNlLFxuICBkYXRhOiBCbG9iIHwgVWludDhBcnJheSB8IEFycmF5QnVmZmVyLFxuICBtZXRhZGF0YT86IE1ldGFkYXRhXG4pOiBVcGxvYWRUYXNrIHtcbiAgcmVmLl90aHJvd0lmUm9vdCgndXBsb2FkQnl0ZXNSZXN1bWFibGUnKTtcbiAgcmV0dXJuIG5ldyBVcGxvYWRUYXNrKHJlZiwgbmV3IEZic0Jsb2IoZGF0YSksIG1ldGFkYXRhKTtcbn1cblxuLyoqXG4gKiBVcGxvYWRzIGEgc3RyaW5nIHRvIHRoaXMgb2JqZWN0J3MgbG9jYXRpb24uXG4gKiBUaGUgdXBsb2FkIGlzIG5vdCByZXN1bWFibGUuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0gU3RvcmFnZVJlZmVyZW5jZSB3aGVyZSBzdHJpbmcgc2hvdWxkIGJlIHVwbG9hZGVkLlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHN0cmluZyB0byB1cGxvYWQuXG4gKiBAcGFyYW0gZm9ybWF0IC0gVGhlIGZvcm1hdCBvZiB0aGUgc3RyaW5nIHRvIHVwbG9hZC5cbiAqIEBwYXJhbSBtZXRhZGF0YSAtIE1ldGFkYXRhIGZvciB0aGUgbmV3bHkgdXBsb2FkZWQgc3RyaW5nLlxuICogQHJldHVybnMgQSBQcm9taXNlIGNvbnRhaW5pbmcgYW4gVXBsb2FkUmVzdWx0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGxvYWRTdHJpbmcoXG4gIHJlZjogUmVmZXJlbmNlLFxuICB2YWx1ZTogc3RyaW5nLFxuICBmb3JtYXQ6IFN0cmluZ0Zvcm1hdCA9IFN0cmluZ0Zvcm1hdC5SQVcsXG4gIG1ldGFkYXRhPzogTWV0YWRhdGFcbik6IFByb21pc2U8VXBsb2FkUmVzdWx0PiB7XG4gIHJlZi5fdGhyb3dJZlJvb3QoJ3VwbG9hZFN0cmluZycpO1xuICBjb25zdCBkYXRhID0gZGF0YUZyb21TdHJpbmcoZm9ybWF0LCB2YWx1ZSk7XG4gIGNvbnN0IG1ldGFkYXRhQ2xvbmUgPSB7IC4uLm1ldGFkYXRhIH0gYXMgTWV0YWRhdGE7XG4gIGlmIChtZXRhZGF0YUNsb25lWydjb250ZW50VHlwZSddID09IG51bGwgJiYgZGF0YS5jb250ZW50VHlwZSAhPSBudWxsKSB7XG4gICAgbWV0YWRhdGFDbG9uZVsnY29udGVudFR5cGUnXSA9IGRhdGEuY29udGVudFR5cGUhO1xuICB9XG4gIHJldHVybiB1cGxvYWRCeXRlcyhyZWYsIGRhdGEuZGF0YSwgbWV0YWRhdGFDbG9uZSk7XG59XG5cbi8qKlxuICogTGlzdCBhbGwgaXRlbXMgKGZpbGVzKSBhbmQgcHJlZml4ZXMgKGZvbGRlcnMpIHVuZGVyIHRoaXMgc3RvcmFnZSByZWZlcmVuY2UuXG4gKlxuICogVGhpcyBpcyBhIGhlbHBlciBtZXRob2QgZm9yIGNhbGxpbmcgbGlzdCgpIHJlcGVhdGVkbHkgdW50aWwgdGhlcmUgYXJlXG4gKiBubyBtb3JlIHJlc3VsdHMuIFRoZSBkZWZhdWx0IHBhZ2luYXRpb24gc2l6ZSBpcyAxMDAwLlxuICpcbiAqIE5vdGU6IFRoZSByZXN1bHRzIG1heSBub3QgYmUgY29uc2lzdGVudCBpZiBvYmplY3RzIGFyZSBjaGFuZ2VkIHdoaWxlIHRoaXNcbiAqIG9wZXJhdGlvbiBpcyBydW5uaW5nLlxuICpcbiAqIFdhcm5pbmc6IGxpc3RBbGwgbWF5IHBvdGVudGlhbGx5IGNvbnN1bWUgdG9vIG1hbnkgcmVzb3VyY2VzIGlmIHRoZXJlIGFyZVxuICogdG9vIG1hbnkgcmVzdWx0cy5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSByZWYgLSBTdG9yYWdlUmVmZXJlbmNlIHRvIGdldCBsaXN0IGZyb20uXG4gKlxuICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbGwgdGhlIGl0ZW1zIGFuZCBwcmVmaXhlcyB1bmRlclxuICogICAgICB0aGUgY3VycmVudCBzdG9yYWdlIHJlZmVyZW5jZS4gYHByZWZpeGVzYCBjb250YWlucyByZWZlcmVuY2VzIHRvXG4gKiAgICAgIHN1Yi1kaXJlY3RvcmllcyBhbmQgYGl0ZW1zYCBjb250YWlucyByZWZlcmVuY2VzIHRvIG9iamVjdHMgaW4gdGhpc1xuICogICAgICBmb2xkZXIuIGBuZXh0UGFnZVRva2VuYCBpcyBuZXZlciByZXR1cm5lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RBbGwocmVmOiBSZWZlcmVuY2UpOiBQcm9taXNlPExpc3RSZXN1bHQ+IHtcbiAgY29uc3QgYWNjdW11bGF0b3I6IExpc3RSZXN1bHQgPSB7XG4gICAgcHJlZml4ZXM6IFtdLFxuICAgIGl0ZW1zOiBbXVxuICB9O1xuICByZXR1cm4gbGlzdEFsbEhlbHBlcihyZWYsIGFjY3VtdWxhdG9yKS50aGVuKCgpID0+IGFjY3VtdWxhdG9yKTtcbn1cblxuLyoqXG4gKiBTZXBhcmF0ZWQgZnJvbSBsaXN0QWxsIGJlY2F1c2UgYXN5bmMgZnVuY3Rpb25zIGNhbid0IHVzZSBcImFyZ3VtZW50c1wiLlxuICogQHBhcmFtIHJlZlxuICogQHBhcmFtIGFjY3VtdWxhdG9yXG4gKiBAcGFyYW0gcGFnZVRva2VuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGxpc3RBbGxIZWxwZXIoXG4gIHJlZjogUmVmZXJlbmNlLFxuICBhY2N1bXVsYXRvcjogTGlzdFJlc3VsdCxcbiAgcGFnZVRva2VuPzogc3RyaW5nXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3Qgb3B0OiBMaXN0T3B0aW9ucyA9IHtcbiAgICAvLyBtYXhSZXN1bHRzIGlzIDEwMDAgYnkgZGVmYXVsdC5cbiAgICBwYWdlVG9rZW5cbiAgfTtcbiAgY29uc3QgbmV4dFBhZ2UgPSBhd2FpdCBsaXN0KHJlZiwgb3B0KTtcbiAgYWNjdW11bGF0b3IucHJlZml4ZXMucHVzaCguLi5uZXh0UGFnZS5wcmVmaXhlcyk7XG4gIGFjY3VtdWxhdG9yLml0ZW1zLnB1c2goLi4ubmV4dFBhZ2UuaXRlbXMpO1xuICBpZiAobmV4dFBhZ2UubmV4dFBhZ2VUb2tlbiAhPSBudWxsKSB7XG4gICAgYXdhaXQgbGlzdEFsbEhlbHBlcihyZWYsIGFjY3VtdWxhdG9yLCBuZXh0UGFnZS5uZXh0UGFnZVRva2VuKTtcbiAgfVxufVxuXG4vKipcbiAqIExpc3QgaXRlbXMgKGZpbGVzKSBhbmQgcHJlZml4ZXMgKGZvbGRlcnMpIHVuZGVyIHRoaXMgc3RvcmFnZSByZWZlcmVuY2UuXG4gKlxuICogTGlzdCBBUEkgaXMgb25seSBhdmFpbGFibGUgZm9yIEZpcmViYXNlIFJ1bGVzIFZlcnNpb24gMi5cbiAqXG4gKiBHQ1MgaXMgYSBrZXktYmxvYiBzdG9yZS4gRmlyZWJhc2UgU3RvcmFnZSBpbXBvc2VzIHRoZSBzZW1hbnRpYyBvZiAnLydcbiAqIGRlbGltaXRlZCBmb2xkZXIgc3RydWN0dXJlLlxuICogUmVmZXIgdG8gR0NTJ3MgTGlzdCBBUEkgaWYgeW91IHdhbnQgdG8gbGVhcm4gbW9yZS5cbiAqXG4gKiBUbyBhZGhlcmUgdG8gRmlyZWJhc2UgUnVsZXMncyBTZW1hbnRpY3MsIEZpcmViYXNlIFN0b3JhZ2UgZG9lcyBub3RcbiAqIHN1cHBvcnQgb2JqZWN0cyB3aG9zZSBwYXRocyBlbmQgd2l0aCBcIi9cIiBvciBjb250YWluIHR3byBjb25zZWN1dGl2ZVxuICogXCIvXCJzLiBGaXJlYmFzZSBTdG9yYWdlIExpc3QgQVBJIHdpbGwgZmlsdGVyIHRoZXNlIHVuc3VwcG9ydGVkIG9iamVjdHMuXG4gKiBsaXN0KCkgbWF5IGZhaWwgaWYgdGhlcmUgYXJlIHRvbyBtYW55IHVuc3VwcG9ydGVkIG9iamVjdHMgaW4gdGhlIGJ1Y2tldC5cbiAqIEBwdWJsaWNcbiAqXG4gKiBAcGFyYW0gcmVmIC0gU3RvcmFnZVJlZmVyZW5jZSB0byBnZXQgbGlzdCBmcm9tLlxuICogQHBhcmFtIG9wdGlvbnMgLSBTZWUgTGlzdE9wdGlvbnMgZm9yIGRldGFpbHMuXG4gKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBpdGVtcyBhbmQgcHJlZml4ZXMuXG4gKiAgICAgIGBwcmVmaXhlc2AgY29udGFpbnMgcmVmZXJlbmNlcyB0byBzdWItZm9sZGVycyBhbmQgYGl0ZW1zYFxuICogICAgICBjb250YWlucyByZWZlcmVuY2VzIHRvIG9iamVjdHMgaW4gdGhpcyBmb2xkZXIuIGBuZXh0UGFnZVRva2VuYFxuICogICAgICBjYW4gYmUgdXNlZCB0byBnZXQgdGhlIHJlc3Qgb2YgdGhlIHJlc3VsdHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaXN0KFxuICByZWY6IFJlZmVyZW5jZSxcbiAgb3B0aW9ucz86IExpc3RPcHRpb25zIHwgbnVsbFxuKTogUHJvbWlzZTxMaXN0UmVzdWx0PiB7XG4gIGlmIChvcHRpb25zICE9IG51bGwpIHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMubWF4UmVzdWx0cyA9PT0gJ251bWJlcicpIHtcbiAgICAgIHZhbGlkYXRlTnVtYmVyKFxuICAgICAgICAnb3B0aW9ucy5tYXhSZXN1bHRzJyxcbiAgICAgICAgLyogbWluVmFsdWU9ICovIDEsXG4gICAgICAgIC8qIG1heFZhbHVlPSAqLyAxMDAwLFxuICAgICAgICBvcHRpb25zLm1heFJlc3VsdHNcbiAgICAgICk7XG4gICAgfVxuICB9XG4gIGNvbnN0IG9wID0gb3B0aW9ucyB8fCB7fTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSByZXF1ZXN0c0xpc3QoXG4gICAgcmVmLnN0b3JhZ2UsXG4gICAgcmVmLl9sb2NhdGlvbixcbiAgICAvKmRlbGltaXRlcj0gKi8gJy8nLFxuICAgIG9wLnBhZ2VUb2tlbixcbiAgICBvcC5tYXhSZXN1bHRzXG4gICk7XG4gIHJldHVybiByZWYuc3RvcmFnZS5tYWtlUmVxdWVzdFdpdGhUb2tlbnMocmVxdWVzdEluZm8sIG5ld1RleHRDb25uZWN0aW9uKTtcbn1cblxuLyoqXG4gKiBBIGBQcm9taXNlYCB0aGF0IHJlc29sdmVzIHdpdGggdGhlIG1ldGFkYXRhIGZvciB0aGlzIG9iamVjdC4gSWYgdGhpc1xuICogb2JqZWN0IGRvZXNuJ3QgZXhpc3Qgb3IgbWV0YWRhdGEgY2Fubm90IGJlIHJldHJpZXZlZCwgdGhlIHByb21pc2UgaXNcbiAqIHJlamVjdGVkLlxuICogQHB1YmxpY1xuICogQHBhcmFtIHJlZiAtIFN0b3JhZ2VSZWZlcmVuY2UgdG8gZ2V0IG1ldGFkYXRhIGZyb20uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNZXRhZGF0YShyZWY6IFJlZmVyZW5jZSk6IFByb21pc2U8TWV0YWRhdGE+IHtcbiAgcmVmLl90aHJvd0lmUm9vdCgnZ2V0TWV0YWRhdGEnKTtcbiAgY29uc3QgcmVxdWVzdEluZm8gPSByZXF1ZXN0c0dldE1ldGFkYXRhKFxuICAgIHJlZi5zdG9yYWdlLFxuICAgIHJlZi5fbG9jYXRpb24sXG4gICAgZ2V0TWFwcGluZ3MoKVxuICApO1xuICByZXR1cm4gcmVmLnN0b3JhZ2UubWFrZVJlcXVlc3RXaXRoVG9rZW5zKHJlcXVlc3RJbmZvLCBuZXdUZXh0Q29ubmVjdGlvbik7XG59XG5cbi8qKlxuICogVXBkYXRlcyB0aGUgbWV0YWRhdGEgZm9yIHRoaXMgb2JqZWN0LlxuICogQHB1YmxpY1xuICogQHBhcmFtIHJlZiAtIFN0b3JhZ2VSZWZlcmVuY2UgdG8gdXBkYXRlIG1ldGFkYXRhIGZvci5cbiAqIEBwYXJhbSBtZXRhZGF0YSAtIFRoZSBuZXcgbWV0YWRhdGEgZm9yIHRoZSBvYmplY3QuXG4gKiAgICAgT25seSB2YWx1ZXMgdGhhdCBoYXZlIGJlZW4gZXhwbGljaXRseSBzZXQgd2lsbCBiZSBjaGFuZ2VkLiBFeHBsaWNpdGx5XG4gKiAgICAgc2V0dGluZyBhIHZhbHVlIHRvIG51bGwgd2lsbCByZW1vdmUgdGhlIG1ldGFkYXRhLlxuICogQHJldHVybnMgQSBgUHJvbWlzZWAgdGhhdCByZXNvbHZlc1xuICogICAgIHdpdGggdGhlIG5ldyBtZXRhZGF0YSBmb3IgdGhpcyBvYmplY3QuXG4gKiAgICAgU2VlIGBmaXJlYmFzZVN0b3JhZ2UuUmVmZXJlbmNlLnByb3RvdHlwZS5nZXRNZXRhZGF0YWBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZU1ldGFkYXRhKFxuICByZWY6IFJlZmVyZW5jZSxcbiAgbWV0YWRhdGE6IFBhcnRpYWw8TWV0YWRhdGE+XG4pOiBQcm9taXNlPE1ldGFkYXRhPiB7XG4gIHJlZi5fdGhyb3dJZlJvb3QoJ3VwZGF0ZU1ldGFkYXRhJyk7XG4gIGNvbnN0IHJlcXVlc3RJbmZvID0gcmVxdWVzdHNVcGRhdGVNZXRhZGF0YShcbiAgICByZWYuc3RvcmFnZSxcbiAgICByZWYuX2xvY2F0aW9uLFxuICAgIG1ldGFkYXRhLFxuICAgIGdldE1hcHBpbmdzKClcbiAgKTtcbiAgcmV0dXJuIHJlZi5zdG9yYWdlLm1ha2VSZXF1ZXN0V2l0aFRva2VucyhyZXF1ZXN0SW5mbywgbmV3VGV4dENvbm5lY3Rpb24pO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGRvd25sb2FkIFVSTCBmb3IgdGhlIGdpdmVuIFJlZmVyZW5jZS5cbiAqIEBwdWJsaWNcbiAqIEByZXR1cm5zIEEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgZG93bmxvYWRcbiAqICAgICBVUkwgZm9yIHRoaXMgb2JqZWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RG93bmxvYWRVUkwocmVmOiBSZWZlcmVuY2UpOiBQcm9taXNlPHN0cmluZz4ge1xuICByZWYuX3Rocm93SWZSb290KCdnZXREb3dubG9hZFVSTCcpO1xuICBjb25zdCByZXF1ZXN0SW5mbyA9IHJlcXVlc3RzR2V0RG93bmxvYWRVcmwoXG4gICAgcmVmLnN0b3JhZ2UsXG4gICAgcmVmLl9sb2NhdGlvbixcbiAgICBnZXRNYXBwaW5ncygpXG4gICk7XG4gIHJldHVybiByZWYuc3RvcmFnZVxuICAgIC5tYWtlUmVxdWVzdFdpdGhUb2tlbnMocmVxdWVzdEluZm8sIG5ld1RleHRDb25uZWN0aW9uKVxuICAgIC50aGVuKHVybCA9PiB7XG4gICAgICBpZiAodXJsID09PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5vRG93bmxvYWRVUkwoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB1cmw7XG4gICAgfSk7XG59XG5cbi8qKlxuICogRGVsZXRlcyB0aGUgb2JqZWN0IGF0IHRoaXMgbG9jYXRpb24uXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0gU3RvcmFnZVJlZmVyZW5jZSBmb3Igb2JqZWN0IHRvIGRlbGV0ZS5cbiAqIEByZXR1cm5zIEEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgaWYgdGhlIGRlbGV0aW9uIHN1Y2NlZWRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVsZXRlT2JqZWN0KHJlZjogUmVmZXJlbmNlKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJlZi5fdGhyb3dJZlJvb3QoJ2RlbGV0ZU9iamVjdCcpO1xuICBjb25zdCByZXF1ZXN0SW5mbyA9IHJlcXVlc3RzRGVsZXRlT2JqZWN0KHJlZi5zdG9yYWdlLCByZWYuX2xvY2F0aW9uKTtcbiAgcmV0dXJuIHJlZi5zdG9yYWdlLm1ha2VSZXF1ZXN0V2l0aFRva2VucyhyZXF1ZXN0SW5mbywgbmV3VGV4dENvbm5lY3Rpb24pO1xufVxuXG4vKipcbiAqIFJldHVybnMgcmVmZXJlbmNlIGZvciBvYmplY3Qgb2J0YWluZWQgYnkgYXBwZW5kaW5nIGBjaGlsZFBhdGhgIHRvIGByZWZgLlxuICpcbiAqIEBwYXJhbSByZWYgLSBTdG9yYWdlUmVmZXJlbmNlIHRvIGdldCBjaGlsZCBvZi5cbiAqIEBwYXJhbSBjaGlsZFBhdGggLSBDaGlsZCBwYXRoIGZyb20gcHJvdmlkZWQgcmVmLlxuICogQHJldHVybnMgQSByZWZlcmVuY2UgdG8gdGhlIG9iamVjdCBvYnRhaW5lZCBieVxuICogYXBwZW5kaW5nIGNoaWxkUGF0aCwgcmVtb3ZpbmcgYW55IGR1cGxpY2F0ZSwgYmVnaW5uaW5nLCBvciB0cmFpbGluZ1xuICogc2xhc2hlcy5cbiAqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfZ2V0Q2hpbGQocmVmOiBSZWZlcmVuY2UsIGNoaWxkUGF0aDogc3RyaW5nKTogUmVmZXJlbmNlIHtcbiAgY29uc3QgbmV3UGF0aCA9IGNoaWxkKHJlZi5fbG9jYXRpb24ucGF0aCwgY2hpbGRQYXRoKTtcbiAgY29uc3QgbG9jYXRpb24gPSBuZXcgTG9jYXRpb24ocmVmLl9sb2NhdGlvbi5idWNrZXQsIG5ld1BhdGgpO1xuICByZXR1cm4gbmV3IFJlZmVyZW5jZShyZWYuc3RvcmFnZSwgbG9jYXRpb24pO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi9sb2NhdGlvbic7XG5pbXBvcnQgeyBGYWlsUmVxdWVzdCB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vZmFpbHJlcXVlc3QnO1xuaW1wb3J0IHsgUmVxdWVzdCwgbWFrZVJlcXVlc3QgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3JlcXVlc3QnO1xuaW1wb3J0IHsgUmVxdWVzdEluZm8gfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3JlcXVlc3RpbmZvJztcbmltcG9ydCB7IFJlZmVyZW5jZSwgX2dldENoaWxkIH0gZnJvbSAnLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IEZpcmViYXNlQXV0aEludGVybmFsTmFtZSB9IGZyb20gJ0BmaXJlYmFzZS9hdXRoLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHsgQXBwQ2hlY2tJbnRlcm5hbENvbXBvbmVudE5hbWUgfSBmcm9tICdAZmlyZWJhc2UvYXBwLWNoZWNrLWludGVyb3AtdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHtcbiAgRmlyZWJhc2VBcHAsXG4gIEZpcmViYXNlT3B0aW9ucyxcbiAgX2lzRmlyZWJhc2VTZXJ2ZXJBcHBcbn0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQge1xuICBDT05GSUdfU1RPUkFHRV9CVUNLRVRfS0VZLFxuICBERUZBVUxUX0hPU1QsXG4gIERFRkFVTFRfTUFYX09QRVJBVElPTl9SRVRSWV9USU1FLFxuICBERUZBVUxUX01BWF9VUExPQURfUkVUUllfVElNRVxufSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBpbnZhbGlkQXJndW1lbnQsXG4gIGFwcERlbGV0ZWQsXG4gIG5vRGVmYXVsdEJ1Y2tldFxufSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL2Vycm9yJztcbmltcG9ydCB7IHZhbGlkYXRlTnVtYmVyIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi90eXBlJztcbmltcG9ydCB7IEZpcmViYXNlU3RvcmFnZSB9IGZyb20gJy4vcHVibGljLXR5cGVzJztcbmltcG9ydCB7XG4gIGNyZWF0ZU1vY2tVc2VyVG9rZW4sXG4gIEVtdWxhdG9yTW9ja1Rva2VuT3B0aW9ucyxcbiAgaXNDbG91ZFdvcmtzdGF0aW9uLFxuICBwaW5nU2VydmVyLFxuICB1cGRhdGVFbXVsYXRvckJhbm5lclxufSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uLCBDb25uZWN0aW9uVHlwZSB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vY29ubmVjdGlvbic7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1VybChwYXRoPzogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAvXltBLVphLXpdKzpcXC9cXC8vLnRlc3QocGF0aCBhcyBzdHJpbmcpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmaXJlYmFzZVN0b3JhZ2UuUmVmZXJlbmNlIGZvciB0aGUgZ2l2ZW4gdXJsLlxuICovXG5mdW5jdGlvbiByZWZGcm9tVVJMKHNlcnZpY2U6IEZpcmViYXNlU3RvcmFnZUltcGwsIHVybDogc3RyaW5nKTogUmVmZXJlbmNlIHtcbiAgcmV0dXJuIG5ldyBSZWZlcmVuY2Uoc2VydmljZSwgdXJsKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZmlyZWJhc2VTdG9yYWdlLlJlZmVyZW5jZSBmb3IgdGhlIGdpdmVuIHBhdGggaW4gdGhlIGRlZmF1bHRcbiAqIGJ1Y2tldC5cbiAqL1xuZnVuY3Rpb24gcmVmRnJvbVBhdGgoXG4gIHJlZjogRmlyZWJhc2VTdG9yYWdlSW1wbCB8IFJlZmVyZW5jZSxcbiAgcGF0aD86IHN0cmluZ1xuKTogUmVmZXJlbmNlIHtcbiAgaWYgKHJlZiBpbnN0YW5jZW9mIEZpcmViYXNlU3RvcmFnZUltcGwpIHtcbiAgICBjb25zdCBzZXJ2aWNlID0gcmVmO1xuICAgIGlmIChzZXJ2aWNlLl9idWNrZXQgPT0gbnVsbCkge1xuICAgICAgdGhyb3cgbm9EZWZhdWx0QnVja2V0KCk7XG4gICAgfVxuICAgIGNvbnN0IHJlZmVyZW5jZSA9IG5ldyBSZWZlcmVuY2Uoc2VydmljZSwgc2VydmljZS5fYnVja2V0ISk7XG4gICAgaWYgKHBhdGggIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHJlZkZyb21QYXRoKHJlZmVyZW5jZSwgcGF0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZWZlcmVuY2U7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIHJlZiBpcyBhIFJlZmVyZW5jZVxuICAgIGlmIChwYXRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBfZ2V0Q2hpbGQocmVmLCBwYXRoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlZjtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgc3RvcmFnZSBSZWZlcmVuY2UgZm9yIHRoZSBnaXZlbiB1cmwuXG4gKiBAcGFyYW0gc3RvcmFnZSAtIGBTdG9yYWdlYCBpbnN0YW5jZS5cbiAqIEBwYXJhbSB1cmwgLSBVUkwuIElmIGVtcHR5LCByZXR1cm5zIHJvb3QgcmVmZXJlbmNlLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVmKHN0b3JhZ2U6IEZpcmViYXNlU3RvcmFnZUltcGwsIHVybD86IHN0cmluZyk6IFJlZmVyZW5jZTtcbi8qKlxuICogUmV0dXJucyBhIHN0b3JhZ2UgUmVmZXJlbmNlIGZvciB0aGUgZ2l2ZW4gcGF0aCBpbiB0aGVcbiAqIGRlZmF1bHQgYnVja2V0LlxuICogQHBhcmFtIHN0b3JhZ2VPclJlZiAtIGBTdG9yYWdlYCBzZXJ2aWNlIG9yIHN0b3JhZ2UgYFJlZmVyZW5jZWAuXG4gKiBAcGFyYW0gcGF0aE9yVXJsU3RvcmFnZSAtIHBhdGguIElmIGVtcHR5LCByZXR1cm5zIHJvb3QgcmVmZXJlbmNlIChpZiBTdG9yYWdlXG4gKiBpbnN0YW5jZSBwcm92aWRlZCkgb3IgcmV0dXJucyBzYW1lIHJlZmVyZW5jZSAoaWYgUmVmZXJlbmNlIHByb3ZpZGVkKS5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZihcbiAgc3RvcmFnZU9yUmVmOiBGaXJlYmFzZVN0b3JhZ2VJbXBsIHwgUmVmZXJlbmNlLFxuICBwYXRoPzogc3RyaW5nXG4pOiBSZWZlcmVuY2U7XG5leHBvcnQgZnVuY3Rpb24gcmVmKFxuICBzZXJ2aWNlT3JSZWY6IEZpcmViYXNlU3RvcmFnZUltcGwgfCBSZWZlcmVuY2UsXG4gIHBhdGhPclVybD86IHN0cmluZ1xuKTogUmVmZXJlbmNlIHwgbnVsbCB7XG4gIGlmIChwYXRoT3JVcmwgJiYgaXNVcmwocGF0aE9yVXJsKSkge1xuICAgIGlmIChzZXJ2aWNlT3JSZWYgaW5zdGFuY2VvZiBGaXJlYmFzZVN0b3JhZ2VJbXBsKSB7XG4gICAgICByZXR1cm4gcmVmRnJvbVVSTChzZXJ2aWNlT3JSZWYsIHBhdGhPclVybCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IGludmFsaWRBcmd1bWVudChcbiAgICAgICAgJ1RvIHVzZSByZWYoc2VydmljZSwgdXJsKSwgdGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBTdG9yYWdlIGluc3RhbmNlLidcbiAgICAgICk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZWZGcm9tUGF0aChzZXJ2aWNlT3JSZWYsIHBhdGhPclVybCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZXh0cmFjdEJ1Y2tldChcbiAgaG9zdDogc3RyaW5nLFxuICBjb25maWc/OiBGaXJlYmFzZU9wdGlvbnNcbik6IExvY2F0aW9uIHwgbnVsbCB7XG4gIGNvbnN0IGJ1Y2tldFN0cmluZyA9IGNvbmZpZz8uW0NPTkZJR19TVE9SQUdFX0JVQ0tFVF9LRVldO1xuICBpZiAoYnVja2V0U3RyaW5nID09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4gTG9jYXRpb24ubWFrZUZyb21CdWNrZXRTcGVjKGJ1Y2tldFN0cmluZywgaG9zdCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb25uZWN0U3RvcmFnZUVtdWxhdG9yKFxuICBzdG9yYWdlOiBGaXJlYmFzZVN0b3JhZ2VJbXBsLFxuICBob3N0OiBzdHJpbmcsXG4gIHBvcnQ6IG51bWJlcixcbiAgb3B0aW9uczoge1xuICAgIG1vY2tVc2VyVG9rZW4/OiBFbXVsYXRvck1vY2tUb2tlbk9wdGlvbnMgfCBzdHJpbmc7XG4gIH0gPSB7fVxuKTogdm9pZCB7XG4gIHN0b3JhZ2UuaG9zdCA9IGAke2hvc3R9OiR7cG9ydH1gO1xuICBjb25zdCB1c2VTc2wgPSBpc0Nsb3VkV29ya3N0YXRpb24oaG9zdCk7XG4gIC8vIFdvcmthcm91bmQgdG8gZ2V0IGNvb2tpZXMgaW4gRmlyZWJhc2UgU3R1ZGlvXG4gIGlmICh1c2VTc2wpIHtcbiAgICB2b2lkIHBpbmdTZXJ2ZXIoYGh0dHBzOi8vJHtzdG9yYWdlLmhvc3R9L2JgKTtcbiAgICB1cGRhdGVFbXVsYXRvckJhbm5lcignU3RvcmFnZScsIHRydWUpO1xuICB9XG4gIHN0b3JhZ2UuX2lzVXNpbmdFbXVsYXRvciA9IHRydWU7XG4gIHN0b3JhZ2UuX3Byb3RvY29sID0gdXNlU3NsID8gJ2h0dHBzJyA6ICdodHRwJztcbiAgY29uc3QgeyBtb2NrVXNlclRva2VuIH0gPSBvcHRpb25zO1xuICBpZiAobW9ja1VzZXJUb2tlbikge1xuICAgIHN0b3JhZ2UuX292ZXJyaWRlQXV0aFRva2VuID1cbiAgICAgIHR5cGVvZiBtb2NrVXNlclRva2VuID09PSAnc3RyaW5nJ1xuICAgICAgICA/IG1vY2tVc2VyVG9rZW5cbiAgICAgICAgOiBjcmVhdGVNb2NrVXNlclRva2VuKG1vY2tVc2VyVG9rZW4sIHN0b3JhZ2UuYXBwLm9wdGlvbnMucHJvamVjdElkKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgc2VydmljZSB0aGF0IHByb3ZpZGVzIEZpcmViYXNlIFN0b3JhZ2UgUmVmZXJlbmNlIGluc3RhbmNlcy5cbiAqIEBwYXJhbSBvcHRfdXJsIC0gZ3M6Ly8gdXJsIHRvIGEgY3VzdG9tIFN0b3JhZ2UgQnVja2V0XG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBGaXJlYmFzZVN0b3JhZ2VJbXBsIGltcGxlbWVudHMgRmlyZWJhc2VTdG9yYWdlIHtcbiAgX2J1Y2tldDogTG9jYXRpb24gfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIFRoaXMgc3RyaW5nIGNhbiBiZSBpbiB0aGUgZm9ybWF0czpcbiAgICogLSBob3N0XG4gICAqIC0gaG9zdDpwb3J0XG4gICAqL1xuICBwcml2YXRlIF9ob3N0OiBzdHJpbmcgPSBERUZBVUxUX0hPU1Q7XG4gIF9wcm90b2NvbDogc3RyaW5nID0gJ2h0dHBzJztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9hcHBJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3JlcXVlc3RzOiBTZXQ8UmVxdWVzdDx1bmtub3duPj47XG4gIHByaXZhdGUgX2RlbGV0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSBfbWF4T3BlcmF0aW9uUmV0cnlUaW1lOiBudW1iZXI7XG4gIHByaXZhdGUgX21heFVwbG9hZFJldHJ5VGltZTogbnVtYmVyO1xuICBfb3ZlcnJpZGVBdXRoVG9rZW4/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgLyoqXG4gICAgICogRmlyZWJhc2VBcHAgYXNzb2NpYXRlZCB3aXRoIHRoaXMgU3RvcmFnZVNlcnZpY2UgaW5zdGFuY2UuXG4gICAgICovXG4gICAgcmVhZG9ubHkgYXBwOiBGaXJlYmFzZUFwcCxcbiAgICByZWFkb25seSBfYXV0aFByb3ZpZGVyOiBQcm92aWRlcjxGaXJlYmFzZUF1dGhJbnRlcm5hbE5hbWU+LFxuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHJlYWRvbmx5IF9hcHBDaGVja1Byb3ZpZGVyOiBQcm92aWRlcjxBcHBDaGVja0ludGVybmFsQ29tcG9uZW50TmFtZT4sXG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcmVhZG9ubHkgX3VybD86IHN0cmluZyxcbiAgICByZWFkb25seSBfZmlyZWJhc2VWZXJzaW9uPzogc3RyaW5nLFxuICAgIHB1YmxpYyBfaXNVc2luZ0VtdWxhdG9yID0gZmFsc2VcbiAgKSB7XG4gICAgdGhpcy5fbWF4T3BlcmF0aW9uUmV0cnlUaW1lID0gREVGQVVMVF9NQVhfT1BFUkFUSU9OX1JFVFJZX1RJTUU7XG4gICAgdGhpcy5fbWF4VXBsb2FkUmV0cnlUaW1lID0gREVGQVVMVF9NQVhfVVBMT0FEX1JFVFJZX1RJTUU7XG4gICAgdGhpcy5fcmVxdWVzdHMgPSBuZXcgU2V0KCk7XG4gICAgaWYgKF91cmwgIT0gbnVsbCkge1xuICAgICAgdGhpcy5fYnVja2V0ID0gTG9jYXRpb24ubWFrZUZyb21CdWNrZXRTcGVjKF91cmwsIHRoaXMuX2hvc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9idWNrZXQgPSBleHRyYWN0QnVja2V0KHRoaXMuX2hvc3QsIHRoaXMuYXBwLm9wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaG9zdCBzdHJpbmcgZm9yIHRoaXMgc2VydmljZSwgaW4gdGhlIGZvcm0gb2YgYGhvc3RgIG9yXG4gICAqIGBob3N0OnBvcnRgLlxuICAgKi9cbiAgZ2V0IGhvc3QoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5faG9zdDtcbiAgfVxuXG4gIHNldCBob3N0KGhvc3Q6IHN0cmluZykge1xuICAgIHRoaXMuX2hvc3QgPSBob3N0O1xuICAgIGlmICh0aGlzLl91cmwgIT0gbnVsbCkge1xuICAgICAgdGhpcy5fYnVja2V0ID0gTG9jYXRpb24ubWFrZUZyb21CdWNrZXRTcGVjKHRoaXMuX3VybCwgaG9zdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2J1Y2tldCA9IGV4dHJhY3RCdWNrZXQoaG9zdCwgdGhpcy5hcHAub3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIHRpbWUgdG8gcmV0cnkgdXBsb2FkcyBpbiBtaWxsaXNlY29uZHMuXG4gICAqL1xuICBnZXQgbWF4VXBsb2FkUmV0cnlUaW1lKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX21heFVwbG9hZFJldHJ5VGltZTtcbiAgfVxuXG4gIHNldCBtYXhVcGxvYWRSZXRyeVRpbWUodGltZTogbnVtYmVyKSB7XG4gICAgdmFsaWRhdGVOdW1iZXIoXG4gICAgICAndGltZScsXG4gICAgICAvKiBtaW5WYWx1ZT0qLyAwLFxuICAgICAgLyogbWF4VmFsdWU9ICovIE51bWJlci5QT1NJVElWRV9JTkZJTklUWSxcbiAgICAgIHRpbWVcbiAgICApO1xuICAgIHRoaXMuX21heFVwbG9hZFJldHJ5VGltZSA9IHRpbWU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG1heGltdW0gdGltZSB0byByZXRyeSBvcGVyYXRpb25zIG90aGVyIHRoYW4gdXBsb2FkcyBvciBkb3dubG9hZHMgaW5cbiAgICogbWlsbGlzZWNvbmRzLlxuICAgKi9cbiAgZ2V0IG1heE9wZXJhdGlvblJldHJ5VGltZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9tYXhPcGVyYXRpb25SZXRyeVRpbWU7XG4gIH1cblxuICBzZXQgbWF4T3BlcmF0aW9uUmV0cnlUaW1lKHRpbWU6IG51bWJlcikge1xuICAgIHZhbGlkYXRlTnVtYmVyKFxuICAgICAgJ3RpbWUnLFxuICAgICAgLyogbWluVmFsdWU9Ki8gMCxcbiAgICAgIC8qIG1heFZhbHVlPSAqLyBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFksXG4gICAgICB0aW1lXG4gICAgKTtcbiAgICB0aGlzLl9tYXhPcGVyYXRpb25SZXRyeVRpbWUgPSB0aW1lO1xuICB9XG5cbiAgYXN5bmMgX2dldEF1dGhUb2tlbigpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICBpZiAodGhpcy5fb3ZlcnJpZGVBdXRoVG9rZW4pIHtcbiAgICAgIHJldHVybiB0aGlzLl9vdmVycmlkZUF1dGhUb2tlbjtcbiAgICB9XG4gICAgY29uc3QgYXV0aCA9IHRoaXMuX2F1dGhQcm92aWRlci5nZXRJbW1lZGlhdGUoeyBvcHRpb25hbDogdHJ1ZSB9KTtcbiAgICBpZiAoYXV0aCkge1xuICAgICAgY29uc3QgdG9rZW5EYXRhID0gYXdhaXQgYXV0aC5nZXRUb2tlbigpO1xuICAgICAgaWYgKHRva2VuRGF0YSAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdG9rZW5EYXRhLmFjY2Vzc1Rva2VuO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIF9nZXRBcHBDaGVja1Rva2VuKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmFwcCkgJiYgdGhpcy5hcHAuc2V0dGluZ3MuYXBwQ2hlY2tUb2tlbikge1xuICAgICAgcmV0dXJuIHRoaXMuYXBwLnNldHRpbmdzLmFwcENoZWNrVG9rZW47XG4gICAgfVxuICAgIGNvbnN0IGFwcENoZWNrID0gdGhpcy5fYXBwQ2hlY2tQcm92aWRlci5nZXRJbW1lZGlhdGUoeyBvcHRpb25hbDogdHJ1ZSB9KTtcbiAgICBpZiAoYXBwQ2hlY2spIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGFwcENoZWNrLmdldFRva2VuKCk7XG4gICAgICAvLyBUT0RPOiBXaGF0IGRvIHdlIHdhbnQgdG8gZG8gaWYgdGhlcmUgaXMgYW4gZXJyb3IgZ2V0dGluZyB0aGUgdG9rZW4/XG4gICAgICAvLyBDb250ZXh0OiBhcHBDaGVjay5nZXRUb2tlbigpIHdpbGwgbmV2ZXIgdGhyb3cgZXZlbiBpZiBhbiBlcnJvciBoYXBwZW5lZC4gSW4gdGhlIGVycm9yIGNhc2UsIGEgZHVtbXkgdG9rZW4gd2lsbCBiZVxuICAgICAgLy8gcmV0dXJuZWQgYWxvbmcgd2l0aCBhbiBlcnJvciBmaWVsZCBkZXNjcmliaW5nIHRoZSBlcnJvci4gSW4gZ2VuZXJhbCwgd2Ugc2hvdWxkbid0IGNhcmUgYWJvdXQgdGhlIGVycm9yIGNvbmRpdGlvbiBhbmQganVzdCB1c2VcbiAgICAgIC8vIHRoZSB0b2tlbiAoYWN0dWFsIG9yIGR1bW15KSB0byBzZW5kIHJlcXVlc3RzLlxuICAgICAgcmV0dXJuIHJlc3VsdC50b2tlbjtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogU3RvcCBydW5uaW5nIHJlcXVlc3RzIGFuZCBwcmV2ZW50IG1vcmUgZnJvbSBiZWluZyBjcmVhdGVkLlxuICAgKi9cbiAgX2RlbGV0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuX2RlbGV0ZWQpIHtcbiAgICAgIHRoaXMuX2RlbGV0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5fcmVxdWVzdHMuZm9yRWFjaChyZXF1ZXN0ID0+IHJlcXVlc3QuY2FuY2VsKCkpO1xuICAgICAgdGhpcy5fcmVxdWVzdHMuY2xlYXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBuZXcgZmlyZWJhc2VTdG9yYWdlLlJlZmVyZW5jZSBvYmplY3QgcmVmZXJlbmNpbmcgdGhpcyBTdG9yYWdlU2VydmljZVxuICAgKiBhdCB0aGUgZ2l2ZW4gTG9jYXRpb24uXG4gICAqL1xuICBfbWFrZVN0b3JhZ2VSZWZlcmVuY2UobG9jOiBMb2NhdGlvbik6IFJlZmVyZW5jZSB7XG4gICAgcmV0dXJuIG5ldyBSZWZlcmVuY2UodGhpcywgbG9jKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gcmVxdWVzdEluZm8gLSBIVFRQIFJlcXVlc3RJbmZvIG9iamVjdFxuICAgKiBAcGFyYW0gYXV0aFRva2VuIC0gRmlyZWJhc2UgYXV0aCB0b2tlblxuICAgKi9cbiAgX21ha2VSZXF1ZXN0PEkgZXh0ZW5kcyBDb25uZWN0aW9uVHlwZSwgTz4oXG4gICAgcmVxdWVzdEluZm86IFJlcXVlc3RJbmZvPEksIE8+LFxuICAgIHJlcXVlc3RGYWN0b3J5OiAoKSA9PiBDb25uZWN0aW9uPEk+LFxuICAgIGF1dGhUb2tlbjogc3RyaW5nIHwgbnVsbCxcbiAgICBhcHBDaGVja1Rva2VuOiBzdHJpbmcgfCBudWxsLFxuICAgIHJldHJ5ID0gdHJ1ZVxuICApOiBSZXF1ZXN0PE8+IHtcbiAgICBpZiAoIXRoaXMuX2RlbGV0ZWQpIHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBtYWtlUmVxdWVzdChcbiAgICAgICAgcmVxdWVzdEluZm8sXG4gICAgICAgIHRoaXMuX2FwcElkLFxuICAgICAgICBhdXRoVG9rZW4sXG4gICAgICAgIGFwcENoZWNrVG9rZW4sXG4gICAgICAgIHJlcXVlc3RGYWN0b3J5LFxuICAgICAgICB0aGlzLl9maXJlYmFzZVZlcnNpb24sXG4gICAgICAgIHJldHJ5LFxuICAgICAgICB0aGlzLl9pc1VzaW5nRW11bGF0b3JcbiAgICAgICk7XG4gICAgICB0aGlzLl9yZXF1ZXN0cy5hZGQocmVxdWVzdCk7XG4gICAgICAvLyBSZXF1ZXN0IHJlbW92ZXMgaXRzZWxmIGZyb20gc2V0IHdoZW4gY29tcGxldGUuXG4gICAgICByZXF1ZXN0LmdldFByb21pc2UoKS50aGVuKFxuICAgICAgICAoKSA9PiB0aGlzLl9yZXF1ZXN0cy5kZWxldGUocmVxdWVzdCksXG4gICAgICAgICgpID0+IHRoaXMuX3JlcXVlc3RzLmRlbGV0ZShyZXF1ZXN0KVxuICAgICAgKTtcbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbmV3IEZhaWxSZXF1ZXN0KGFwcERlbGV0ZWQoKSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgbWFrZVJlcXVlc3RXaXRoVG9rZW5zPEkgZXh0ZW5kcyBDb25uZWN0aW9uVHlwZSwgTz4oXG4gICAgcmVxdWVzdEluZm86IFJlcXVlc3RJbmZvPEksIE8+LFxuICAgIHJlcXVlc3RGYWN0b3J5OiAoKSA9PiBDb25uZWN0aW9uPEk+XG4gICk6IFByb21pc2U8Tz4ge1xuICAgIGNvbnN0IFthdXRoVG9rZW4sIGFwcENoZWNrVG9rZW5dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgdGhpcy5fZ2V0QXV0aFRva2VuKCksXG4gICAgICB0aGlzLl9nZXRBcHBDaGVja1Rva2VuKClcbiAgICBdKTtcblxuICAgIHJldHVybiB0aGlzLl9tYWtlUmVxdWVzdChcbiAgICAgIHJlcXVlc3RJbmZvLFxuICAgICAgcmVxdWVzdEZhY3RvcnksXG4gICAgICBhdXRoVG9rZW4sXG4gICAgICBhcHBDaGVja1Rva2VuXG4gICAgKS5nZXRQcm9taXNlKCk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIFR5cGUgY29uc3RhbnQgZm9yIEZpcmViYXNlIFN0b3JhZ2UuXG4gKi9cbmV4cG9ydCBjb25zdCBTVE9SQUdFX1RZUEUgPSAnc3RvcmFnZSc7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7IF9nZXRQcm92aWRlciwgRmlyZWJhc2VBcHAsIGdldEFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuXG5pbXBvcnQge1xuICByZWYgYXMgcmVmSW50ZXJuYWwsXG4gIEZpcmViYXNlU3RvcmFnZUltcGwsXG4gIGNvbm5lY3RTdG9yYWdlRW11bGF0b3IgYXMgY29ubmVjdEVtdWxhdG9ySW50ZXJuYWxcbn0gZnJvbSAnLi9zZXJ2aWNlJztcbmltcG9ydCB7IFByb3ZpZGVyIH0gZnJvbSAnQGZpcmViYXNlL2NvbXBvbmVudCc7XG5cbmltcG9ydCB7XG4gIFN0b3JhZ2VSZWZlcmVuY2UsXG4gIEZpcmViYXNlU3RvcmFnZSxcbiAgVXBsb2FkUmVzdWx0LFxuICBMaXN0T3B0aW9ucyxcbiAgTGlzdFJlc3VsdCxcbiAgVXBsb2FkVGFzayxcbiAgU2V0dGFibGVNZXRhZGF0YSxcbiAgVXBsb2FkTWV0YWRhdGEsXG4gIEZ1bGxNZXRhZGF0YVxufSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBNZXRhZGF0YSBhcyBNZXRhZGF0YUludGVybmFsIH0gZnJvbSAnLi9tZXRhZGF0YSc7XG5pbXBvcnQge1xuICB1cGxvYWRCeXRlcyBhcyB1cGxvYWRCeXRlc0ludGVybmFsLFxuICB1cGxvYWRCeXRlc1Jlc3VtYWJsZSBhcyB1cGxvYWRCeXRlc1Jlc3VtYWJsZUludGVybmFsLFxuICB1cGxvYWRTdHJpbmcgYXMgdXBsb2FkU3RyaW5nSW50ZXJuYWwsXG4gIGdldE1ldGFkYXRhIGFzIGdldE1ldGFkYXRhSW50ZXJuYWwsXG4gIHVwZGF0ZU1ldGFkYXRhIGFzIHVwZGF0ZU1ldGFkYXRhSW50ZXJuYWwsXG4gIGxpc3QgYXMgbGlzdEludGVybmFsLFxuICBsaXN0QWxsIGFzIGxpc3RBbGxJbnRlcm5hbCxcbiAgZ2V0RG93bmxvYWRVUkwgYXMgZ2V0RG93bmxvYWRVUkxJbnRlcm5hbCxcbiAgZGVsZXRlT2JqZWN0IGFzIGRlbGV0ZU9iamVjdEludGVybmFsLFxuICBSZWZlcmVuY2UsXG4gIF9nZXRDaGlsZCBhcyBfZ2V0Q2hpbGRJbnRlcm5hbCxcbiAgZ2V0Qnl0ZXNJbnRlcm5hbFxufSBmcm9tICcuL3JlZmVyZW5jZSc7XG5pbXBvcnQgeyBTVE9SQUdFX1RZUEUgfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBFbXVsYXRvck1vY2tUb2tlbk9wdGlvbnMsXG4gIGdldE1vZHVsYXJJbnN0YW5jZSxcbiAgZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdG5hbWVBbmRQb3J0XG59IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IFN0cmluZ0Zvcm1hdCB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vc3RyaW5nJztcblxuZXhwb3J0IHsgRW11bGF0b3JNb2NrVG9rZW5PcHRpb25zIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5leHBvcnQgeyBTdG9yYWdlRXJyb3IsIFN0b3JhZ2VFcnJvckNvZGUgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL2Vycm9yJztcblxuLyoqXG4gKiBQdWJsaWMgdHlwZXMuXG4gKi9cbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLXR5cGVzJztcblxuZXhwb3J0IHsgTG9jYXRpb24gYXMgX0xvY2F0aW9uIH0gZnJvbSAnLi9pbXBsZW1lbnRhdGlvbi9sb2NhdGlvbic7XG5leHBvcnQgeyBVcGxvYWRUYXNrIGFzIF9VcGxvYWRUYXNrIH0gZnJvbSAnLi90YXNrJztcbmV4cG9ydCB0eXBlIHsgUmVmZXJlbmNlIGFzIF9SZWZlcmVuY2UgfSBmcm9tICcuL3JlZmVyZW5jZSc7XG5leHBvcnQgdHlwZSB7IEZpcmViYXNlU3RvcmFnZUltcGwgYXMgX0ZpcmViYXNlU3RvcmFnZUltcGwgfSBmcm9tICcuL3NlcnZpY2UnO1xuZXhwb3J0IHsgRmJzQmxvYiBhcyBfRmJzQmxvYiB9IGZyb20gJy4vaW1wbGVtZW50YXRpb24vYmxvYic7XG5leHBvcnQgeyBkYXRhRnJvbVN0cmluZyBhcyBfZGF0YUZyb21TdHJpbmcgfSBmcm9tICcuL2ltcGxlbWVudGF0aW9uL3N0cmluZyc7XG5leHBvcnQge1xuICBpbnZhbGlkUm9vdE9wZXJhdGlvbiBhcyBfaW52YWxpZFJvb3RPcGVyYXRpb24sXG4gIGludmFsaWRBcmd1bWVudCBhcyBfaW52YWxpZEFyZ3VtZW50XG59IGZyb20gJy4vaW1wbGVtZW50YXRpb24vZXJyb3InO1xuZXhwb3J0IHtcbiAgVGFza0V2ZW50IGFzIF9UYXNrRXZlbnQsXG4gIFRhc2tTdGF0ZSBhcyBfVGFza1N0YXRlXG59IGZyb20gJy4vaW1wbGVtZW50YXRpb24vdGFza2VudW1zJztcbmV4cG9ydCB7IFN0cmluZ0Zvcm1hdCB9O1xuXG4vKipcbiAqIERvd25sb2FkcyB0aGUgZGF0YSBhdCB0aGUgb2JqZWN0J3MgbG9jYXRpb24uIFJldHVybnMgYW4gZXJyb3IgaWYgdGhlIG9iamVjdFxuICogaXMgbm90IGZvdW5kLlxuICpcbiAqIFRvIHVzZSB0aGlzIGZ1bmN0aW9uYWxpdHksIHlvdSBoYXZlIHRvIHdoaXRlbGlzdCB5b3VyIGFwcCdzIG9yaWdpbiBpbiB5b3VyXG4gKiBDbG91ZCBTdG9yYWdlIGJ1Y2tldC4gU2VlIGFsc29cbiAqIGh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zdG9yYWdlL2RvY3MvY29uZmlndXJpbmctY29yc1xuICpcbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSByZWYgLSBTdG9yYWdlUmVmZXJlbmNlIHdoZXJlIGRhdGEgc2hvdWxkIGJlIGRvd25sb2FkZWQuXG4gKiBAcGFyYW0gbWF4RG93bmxvYWRTaXplQnl0ZXMgLSBJZiBzZXQsIHRoZSBtYXhpbXVtIGFsbG93ZWQgc2l6ZSBpbiBieXRlcyB0b1xuICogcmV0cmlldmUuXG4gKiBAcmV0dXJucyBBIFByb21pc2UgY29udGFpbmluZyB0aGUgb2JqZWN0J3MgYnl0ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEJ5dGVzKFxuICByZWY6IFN0b3JhZ2VSZWZlcmVuY2UsXG4gIG1heERvd25sb2FkU2l6ZUJ5dGVzPzogbnVtYmVyXG4pOiBQcm9taXNlPEFycmF5QnVmZmVyPiB7XG4gIHJlZiA9IGdldE1vZHVsYXJJbnN0YW5jZShyZWYpO1xuICByZXR1cm4gZ2V0Qnl0ZXNJbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlLCBtYXhEb3dubG9hZFNpemVCeXRlcyk7XG59XG5cbi8qKlxuICogVXBsb2FkcyBkYXRhIHRvIHRoaXMgb2JqZWN0J3MgbG9jYXRpb24uXG4gKiBUaGUgdXBsb2FkIGlzIG5vdCByZXN1bWFibGUuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0ge0BsaW5rIFN0b3JhZ2VSZWZlcmVuY2V9IHdoZXJlIGRhdGEgc2hvdWxkIGJlIHVwbG9hZGVkLlxuICogQHBhcmFtIGRhdGEgLSBUaGUgZGF0YSB0byB1cGxvYWQuXG4gKiBAcGFyYW0gbWV0YWRhdGEgLSBNZXRhZGF0YSBmb3IgdGhlIGRhdGEgdG8gdXBsb2FkLlxuICogQHJldHVybnMgQSBQcm9taXNlIGNvbnRhaW5pbmcgYW4gVXBsb2FkUmVzdWx0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGxvYWRCeXRlcyhcbiAgcmVmOiBTdG9yYWdlUmVmZXJlbmNlLFxuICBkYXRhOiBCbG9iIHwgVWludDhBcnJheSB8IEFycmF5QnVmZmVyLFxuICBtZXRhZGF0YT86IFVwbG9hZE1ldGFkYXRhXG4pOiBQcm9taXNlPFVwbG9hZFJlc3VsdD4ge1xuICByZWYgPSBnZXRNb2R1bGFySW5zdGFuY2UocmVmKTtcbiAgcmV0dXJuIHVwbG9hZEJ5dGVzSW50ZXJuYWwoXG4gICAgcmVmIGFzIFJlZmVyZW5jZSxcbiAgICBkYXRhLFxuICAgIG1ldGFkYXRhIGFzIE1ldGFkYXRhSW50ZXJuYWxcbiAgKTtcbn1cblxuLyoqXG4gKiBVcGxvYWRzIGEgc3RyaW5nIHRvIHRoaXMgb2JqZWN0J3MgbG9jYXRpb24uXG4gKiBUaGUgdXBsb2FkIGlzIG5vdCByZXN1bWFibGUuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0ge0BsaW5rIFN0b3JhZ2VSZWZlcmVuY2V9IHdoZXJlIHN0cmluZyBzaG91bGQgYmUgdXBsb2FkZWQuXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgc3RyaW5nIHRvIHVwbG9hZC5cbiAqIEBwYXJhbSBmb3JtYXQgLSBUaGUgZm9ybWF0IG9mIHRoZSBzdHJpbmcgdG8gdXBsb2FkLlxuICogQHBhcmFtIG1ldGFkYXRhIC0gTWV0YWRhdGEgZm9yIHRoZSBzdHJpbmcgdG8gdXBsb2FkLlxuICogQHJldHVybnMgQSBQcm9taXNlIGNvbnRhaW5pbmcgYW4gVXBsb2FkUmVzdWx0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGxvYWRTdHJpbmcoXG4gIHJlZjogU3RvcmFnZVJlZmVyZW5jZSxcbiAgdmFsdWU6IHN0cmluZyxcbiAgZm9ybWF0PzogU3RyaW5nRm9ybWF0LFxuICBtZXRhZGF0YT86IFVwbG9hZE1ldGFkYXRhXG4pOiBQcm9taXNlPFVwbG9hZFJlc3VsdD4ge1xuICByZWYgPSBnZXRNb2R1bGFySW5zdGFuY2UocmVmKTtcbiAgcmV0dXJuIHVwbG9hZFN0cmluZ0ludGVybmFsKFxuICAgIHJlZiBhcyBSZWZlcmVuY2UsXG4gICAgdmFsdWUsXG4gICAgZm9ybWF0LFxuICAgIG1ldGFkYXRhIGFzIE1ldGFkYXRhSW50ZXJuYWxcbiAgKTtcbn1cblxuLyoqXG4gKiBVcGxvYWRzIGRhdGEgdG8gdGhpcyBvYmplY3QncyBsb2NhdGlvbi5cbiAqIFRoZSB1cGxvYWQgY2FuIGJlIHBhdXNlZCBhbmQgcmVzdW1lZCwgYW5kIGV4cG9zZXMgcHJvZ3Jlc3MgdXBkYXRlcy5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSByZWYgLSB7QGxpbmsgU3RvcmFnZVJlZmVyZW5jZX0gd2hlcmUgZGF0YSBzaG91bGQgYmUgdXBsb2FkZWQuXG4gKiBAcGFyYW0gZGF0YSAtIFRoZSBkYXRhIHRvIHVwbG9hZC5cbiAqIEBwYXJhbSBtZXRhZGF0YSAtIE1ldGFkYXRhIGZvciB0aGUgZGF0YSB0byB1cGxvYWQuXG4gKiBAcmV0dXJucyBBbiBVcGxvYWRUYXNrXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGxvYWRCeXRlc1Jlc3VtYWJsZShcbiAgcmVmOiBTdG9yYWdlUmVmZXJlbmNlLFxuICBkYXRhOiBCbG9iIHwgVWludDhBcnJheSB8IEFycmF5QnVmZmVyLFxuICBtZXRhZGF0YT86IFVwbG9hZE1ldGFkYXRhXG4pOiBVcGxvYWRUYXNrIHtcbiAgcmVmID0gZ2V0TW9kdWxhckluc3RhbmNlKHJlZik7XG4gIHJldHVybiB1cGxvYWRCeXRlc1Jlc3VtYWJsZUludGVybmFsKFxuICAgIHJlZiBhcyBSZWZlcmVuY2UsXG4gICAgZGF0YSxcbiAgICBtZXRhZGF0YSBhcyBNZXRhZGF0YUludGVybmFsXG4gICkgYXMgVXBsb2FkVGFzaztcbn1cblxuLyoqXG4gKiBBIGBQcm9taXNlYCB0aGF0IHJlc29sdmVzIHdpdGggdGhlIG1ldGFkYXRhIGZvciB0aGlzIG9iamVjdC4gSWYgdGhpc1xuICogb2JqZWN0IGRvZXNuJ3QgZXhpc3Qgb3IgbWV0YWRhdGEgY2Fubm90IGJlIHJldHJpZXZlZCwgdGhlIHByb21pc2UgaXNcbiAqIHJlamVjdGVkLlxuICogQHB1YmxpY1xuICogQHBhcmFtIHJlZiAtIHtAbGluayBTdG9yYWdlUmVmZXJlbmNlfSB0byBnZXQgbWV0YWRhdGEgZnJvbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1ldGFkYXRhKHJlZjogU3RvcmFnZVJlZmVyZW5jZSk6IFByb21pc2U8RnVsbE1ldGFkYXRhPiB7XG4gIHJlZiA9IGdldE1vZHVsYXJJbnN0YW5jZShyZWYpO1xuICByZXR1cm4gZ2V0TWV0YWRhdGFJbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlKSBhcyBQcm9taXNlPEZ1bGxNZXRhZGF0YT47XG59XG5cbi8qKlxuICogVXBkYXRlcyB0aGUgbWV0YWRhdGEgZm9yIHRoaXMgb2JqZWN0LlxuICogQHB1YmxpY1xuICogQHBhcmFtIHJlZiAtIHtAbGluayBTdG9yYWdlUmVmZXJlbmNlfSB0byB1cGRhdGUgbWV0YWRhdGEgZm9yLlxuICogQHBhcmFtIG1ldGFkYXRhIC0gVGhlIG5ldyBtZXRhZGF0YSBmb3IgdGhlIG9iamVjdC5cbiAqICAgICBPbmx5IHZhbHVlcyB0aGF0IGhhdmUgYmVlbiBleHBsaWNpdGx5IHNldCB3aWxsIGJlIGNoYW5nZWQuIEV4cGxpY2l0bHlcbiAqICAgICBzZXR0aW5nIGEgdmFsdWUgdG8gbnVsbCB3aWxsIHJlbW92ZSB0aGUgbWV0YWRhdGEuXG4gKiBAcmV0dXJucyBBIGBQcm9taXNlYCB0aGF0IHJlc29sdmVzIHdpdGggdGhlIG5ldyBtZXRhZGF0YSBmb3IgdGhpcyBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVNZXRhZGF0YShcbiAgcmVmOiBTdG9yYWdlUmVmZXJlbmNlLFxuICBtZXRhZGF0YTogU2V0dGFibGVNZXRhZGF0YVxuKTogUHJvbWlzZTxGdWxsTWV0YWRhdGE+IHtcbiAgcmVmID0gZ2V0TW9kdWxhckluc3RhbmNlKHJlZik7XG4gIHJldHVybiB1cGRhdGVNZXRhZGF0YUludGVybmFsKFxuICAgIHJlZiBhcyBSZWZlcmVuY2UsXG4gICAgbWV0YWRhdGEgYXMgUGFydGlhbDxNZXRhZGF0YUludGVybmFsPlxuICApIGFzIFByb21pc2U8RnVsbE1ldGFkYXRhPjtcbn1cblxuLyoqXG4gKiBMaXN0IGl0ZW1zIChmaWxlcykgYW5kIHByZWZpeGVzIChmb2xkZXJzKSB1bmRlciB0aGlzIHN0b3JhZ2UgcmVmZXJlbmNlLlxuICpcbiAqIExpc3QgQVBJIGlzIG9ubHkgYXZhaWxhYmxlIGZvciBGaXJlYmFzZSBSdWxlcyBWZXJzaW9uIDIuXG4gKlxuICogR0NTIGlzIGEga2V5LWJsb2Igc3RvcmUuIEZpcmViYXNlIFN0b3JhZ2UgaW1wb3NlcyB0aGUgc2VtYW50aWMgb2YgJy8nXG4gKiBkZWxpbWl0ZWQgZm9sZGVyIHN0cnVjdHVyZS5cbiAqIFJlZmVyIHRvIEdDUydzIExpc3QgQVBJIGlmIHlvdSB3YW50IHRvIGxlYXJuIG1vcmUuXG4gKlxuICogVG8gYWRoZXJlIHRvIEZpcmViYXNlIFJ1bGVzJ3MgU2VtYW50aWNzLCBGaXJlYmFzZSBTdG9yYWdlIGRvZXMgbm90XG4gKiBzdXBwb3J0IG9iamVjdHMgd2hvc2UgcGF0aHMgZW5kIHdpdGggXCIvXCIgb3IgY29udGFpbiB0d28gY29uc2VjdXRpdmVcbiAqIFwiL1wicy4gRmlyZWJhc2UgU3RvcmFnZSBMaXN0IEFQSSB3aWxsIGZpbHRlciB0aGVzZSB1bnN1cHBvcnRlZCBvYmplY3RzLlxuICogbGlzdCgpIG1heSBmYWlsIGlmIHRoZXJlIGFyZSB0b28gbWFueSB1bnN1cHBvcnRlZCBvYmplY3RzIGluIHRoZSBidWNrZXQuXG4gKiBAcHVibGljXG4gKlxuICogQHBhcmFtIHJlZiAtIHtAbGluayBTdG9yYWdlUmVmZXJlbmNlfSB0byBnZXQgbGlzdCBmcm9tLlxuICogQHBhcmFtIG9wdGlvbnMgLSBTZWUge0BsaW5rIExpc3RPcHRpb25zfSBmb3IgZGV0YWlscy5cbiAqIEByZXR1cm5zIEEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgaXRlbXMgYW5kIHByZWZpeGVzLlxuICogICAgICBgcHJlZml4ZXNgIGNvbnRhaW5zIHJlZmVyZW5jZXMgdG8gc3ViLWZvbGRlcnMgYW5kIGBpdGVtc2BcbiAqICAgICAgY29udGFpbnMgcmVmZXJlbmNlcyB0byBvYmplY3RzIGluIHRoaXMgZm9sZGVyLiBgbmV4dFBhZ2VUb2tlbmBcbiAqICAgICAgY2FuIGJlIHVzZWQgdG8gZ2V0IHRoZSByZXN0IG9mIHRoZSByZXN1bHRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGlzdChcbiAgcmVmOiBTdG9yYWdlUmVmZXJlbmNlLFxuICBvcHRpb25zPzogTGlzdE9wdGlvbnNcbik6IFByb21pc2U8TGlzdFJlc3VsdD4ge1xuICByZWYgPSBnZXRNb2R1bGFySW5zdGFuY2UocmVmKTtcbiAgcmV0dXJuIGxpc3RJbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlLCBvcHRpb25zKTtcbn1cblxuLyoqXG4gKiBMaXN0IGFsbCBpdGVtcyAoZmlsZXMpIGFuZCBwcmVmaXhlcyAoZm9sZGVycykgdW5kZXIgdGhpcyBzdG9yYWdlIHJlZmVyZW5jZS5cbiAqXG4gKiBUaGlzIGlzIGEgaGVscGVyIG1ldGhvZCBmb3IgY2FsbGluZyBsaXN0KCkgcmVwZWF0ZWRseSB1bnRpbCB0aGVyZSBhcmVcbiAqIG5vIG1vcmUgcmVzdWx0cy4gVGhlIGRlZmF1bHQgcGFnaW5hdGlvbiBzaXplIGlzIDEwMDAuXG4gKlxuICogTm90ZTogVGhlIHJlc3VsdHMgbWF5IG5vdCBiZSBjb25zaXN0ZW50IGlmIG9iamVjdHMgYXJlIGNoYW5nZWQgd2hpbGUgdGhpc1xuICogb3BlcmF0aW9uIGlzIHJ1bm5pbmcuXG4gKlxuICogV2FybmluZzogYGxpc3RBbGxgIG1heSBwb3RlbnRpYWxseSBjb25zdW1lIHRvbyBtYW55IHJlc291cmNlcyBpZiB0aGVyZSBhcmVcbiAqIHRvbyBtYW55IHJlc3VsdHMuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0ge0BsaW5rIFN0b3JhZ2VSZWZlcmVuY2V9IHRvIGdldCBsaXN0IGZyb20uXG4gKlxuICogQHJldHVybnMgQSBgUHJvbWlzZWAgdGhhdCByZXNvbHZlcyB3aXRoIGFsbCB0aGUgaXRlbXMgYW5kIHByZWZpeGVzIHVuZGVyXG4gKiAgICAgIHRoZSBjdXJyZW50IHN0b3JhZ2UgcmVmZXJlbmNlLiBgcHJlZml4ZXNgIGNvbnRhaW5zIHJlZmVyZW5jZXMgdG9cbiAqICAgICAgc3ViLWRpcmVjdG9yaWVzIGFuZCBgaXRlbXNgIGNvbnRhaW5zIHJlZmVyZW5jZXMgdG8gb2JqZWN0cyBpbiB0aGlzXG4gKiAgICAgIGZvbGRlci4gYG5leHRQYWdlVG9rZW5gIGlzIG5ldmVyIHJldHVybmVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGlzdEFsbChyZWY6IFN0b3JhZ2VSZWZlcmVuY2UpOiBQcm9taXNlPExpc3RSZXN1bHQ+IHtcbiAgcmVmID0gZ2V0TW9kdWxhckluc3RhbmNlKHJlZik7XG4gIHJldHVybiBsaXN0QWxsSW50ZXJuYWwocmVmIGFzIFJlZmVyZW5jZSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgZG93bmxvYWQgVVJMIGZvciB0aGUgZ2l2ZW4ge0BsaW5rIFN0b3JhZ2VSZWZlcmVuY2V9LlxuICogQHB1YmxpY1xuICogQHBhcmFtIHJlZiAtIHtAbGluayBTdG9yYWdlUmVmZXJlbmNlfSB0byBnZXQgdGhlIGRvd25sb2FkIFVSTCBmb3IuXG4gKiBAcmV0dXJucyBBIGBQcm9taXNlYCB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGRvd25sb2FkXG4gKiAgICAgVVJMIGZvciB0aGlzIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERvd25sb2FkVVJMKHJlZjogU3RvcmFnZVJlZmVyZW5jZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJlZiA9IGdldE1vZHVsYXJJbnN0YW5jZShyZWYpO1xuICByZXR1cm4gZ2V0RG93bmxvYWRVUkxJbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlKTtcbn1cblxuLyoqXG4gKiBEZWxldGVzIHRoZSBvYmplY3QgYXQgdGhpcyBsb2NhdGlvbi5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSByZWYgLSB7QGxpbmsgU3RvcmFnZVJlZmVyZW5jZX0gZm9yIG9iamVjdCB0byBkZWxldGUuXG4gKiBAcmV0dXJucyBBIGBQcm9taXNlYCB0aGF0IHJlc29sdmVzIGlmIHRoZSBkZWxldGlvbiBzdWNjZWVkcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlbGV0ZU9iamVjdChyZWY6IFN0b3JhZ2VSZWZlcmVuY2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmVmID0gZ2V0TW9kdWxhckluc3RhbmNlKHJlZik7XG4gIHJldHVybiBkZWxldGVPYmplY3RJbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEge0BsaW5rIFN0b3JhZ2VSZWZlcmVuY2V9IGZvciB0aGUgZ2l2ZW4gdXJsLlxuICogQHBhcmFtIHN0b3JhZ2UgLSB7QGxpbmsgRmlyZWJhc2VTdG9yYWdlfSBpbnN0YW5jZS5cbiAqIEBwYXJhbSB1cmwgLSBVUkwuIElmIGVtcHR5LCByZXR1cm5zIHJvb3QgcmVmZXJlbmNlLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVmKHN0b3JhZ2U6IEZpcmViYXNlU3RvcmFnZSwgdXJsPzogc3RyaW5nKTogU3RvcmFnZVJlZmVyZW5jZTtcbi8qKlxuICogUmV0dXJucyBhIHtAbGluayBTdG9yYWdlUmVmZXJlbmNlfSBmb3IgdGhlIGdpdmVuIHBhdGggaW4gdGhlXG4gKiBkZWZhdWx0IGJ1Y2tldC5cbiAqIEBwYXJhbSBzdG9yYWdlT3JSZWYgLSB7QGxpbmsgRmlyZWJhc2VTdG9yYWdlfSBvciB7QGxpbmsgU3RvcmFnZVJlZmVyZW5jZX0uXG4gKiBAcGFyYW0gcGF0aE9yVXJsU3RvcmFnZSAtIHBhdGguIElmIGVtcHR5LCByZXR1cm5zIHJvb3QgcmVmZXJlbmNlIChpZiB7QGxpbmsgRmlyZWJhc2VTdG9yYWdlfVxuICogaW5zdGFuY2UgcHJvdmlkZWQpIG9yIHJldHVybnMgc2FtZSByZWZlcmVuY2UgKGlmIHtAbGluayBTdG9yYWdlUmVmZXJlbmNlfSBwcm92aWRlZCkuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWYoXG4gIHN0b3JhZ2VPclJlZjogRmlyZWJhc2VTdG9yYWdlIHwgU3RvcmFnZVJlZmVyZW5jZSxcbiAgcGF0aD86IHN0cmluZ1xuKTogU3RvcmFnZVJlZmVyZW5jZTtcbmV4cG9ydCBmdW5jdGlvbiByZWYoXG4gIHNlcnZpY2VPclJlZjogRmlyZWJhc2VTdG9yYWdlIHwgU3RvcmFnZVJlZmVyZW5jZSxcbiAgcGF0aE9yVXJsPzogc3RyaW5nXG4pOiBTdG9yYWdlUmVmZXJlbmNlIHwgbnVsbCB7XG4gIHNlcnZpY2VPclJlZiA9IGdldE1vZHVsYXJJbnN0YW5jZShzZXJ2aWNlT3JSZWYpO1xuICByZXR1cm4gcmVmSW50ZXJuYWwoXG4gICAgc2VydmljZU9yUmVmIGFzIEZpcmViYXNlU3RvcmFnZUltcGwgfCBSZWZlcmVuY2UsXG4gICAgcGF0aE9yVXJsXG4gICk7XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfZ2V0Q2hpbGQocmVmOiBTdG9yYWdlUmVmZXJlbmNlLCBjaGlsZFBhdGg6IHN0cmluZyk6IFJlZmVyZW5jZSB7XG4gIHJldHVybiBfZ2V0Q2hpbGRJbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlLCBjaGlsZFBhdGgpO1xufVxuXG4vKipcbiAqIEdldHMgYSB7QGxpbmsgRmlyZWJhc2VTdG9yYWdlfSBpbnN0YW5jZSBmb3IgdGhlIGdpdmVuIEZpcmViYXNlIGFwcC5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSBhcHAgLSBGaXJlYmFzZSBhcHAgdG8gZ2V0IHtAbGluayBGaXJlYmFzZVN0b3JhZ2V9IGluc3RhbmNlIGZvci5cbiAqIEBwYXJhbSBidWNrZXRVcmwgLSBUaGUgZ3M6Ly8gdXJsIHRvIHlvdXIgRmlyZWJhc2UgU3RvcmFnZSBCdWNrZXQuXG4gKiBJZiBub3QgcGFzc2VkLCB1c2VzIHRoZSBhcHAncyBkZWZhdWx0IFN0b3JhZ2UgQnVja2V0LlxuICogQHJldHVybnMgQSB7QGxpbmsgRmlyZWJhc2VTdG9yYWdlfSBpbnN0YW5jZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0b3JhZ2UoXG4gIGFwcDogRmlyZWJhc2VBcHAgPSBnZXRBcHAoKSxcbiAgYnVja2V0VXJsPzogc3RyaW5nXG4pOiBGaXJlYmFzZVN0b3JhZ2Uge1xuICBhcHAgPSBnZXRNb2R1bGFySW5zdGFuY2UoYXBwKTtcbiAgY29uc3Qgc3RvcmFnZVByb3ZpZGVyOiBQcm92aWRlcjwnc3RvcmFnZSc+ID0gX2dldFByb3ZpZGVyKGFwcCwgU1RPUkFHRV9UWVBFKTtcbiAgY29uc3Qgc3RvcmFnZUluc3RhbmNlID0gc3RvcmFnZVByb3ZpZGVyLmdldEltbWVkaWF0ZSh7XG4gICAgaWRlbnRpZmllcjogYnVja2V0VXJsXG4gIH0pO1xuICBjb25zdCBlbXVsYXRvciA9IGdldERlZmF1bHRFbXVsYXRvckhvc3RuYW1lQW5kUG9ydCgnc3RvcmFnZScpO1xuICBpZiAoZW11bGF0b3IpIHtcbiAgICBjb25uZWN0U3RvcmFnZUVtdWxhdG9yKHN0b3JhZ2VJbnN0YW5jZSwgLi4uZW11bGF0b3IpO1xuICB9XG4gIHJldHVybiBzdG9yYWdlSW5zdGFuY2U7XG59XG5cbi8qKlxuICogTW9kaWZ5IHRoaXMge0BsaW5rIEZpcmViYXNlU3RvcmFnZX0gaW5zdGFuY2UgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgQ2xvdWQgU3RvcmFnZSBlbXVsYXRvci5cbiAqXG4gKiBAcGFyYW0gc3RvcmFnZSAtIFRoZSB7QGxpbmsgRmlyZWJhc2VTdG9yYWdlfSBpbnN0YW5jZVxuICogQHBhcmFtIGhvc3QgLSBUaGUgZW11bGF0b3IgaG9zdCAoZXg6IGxvY2FsaG9zdClcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIGVtdWxhdG9yIHBvcnQgKGV4OiA1MDAxKVxuICogQHBhcmFtIG9wdGlvbnMgLSBFbXVsYXRvciBvcHRpb25zLiBgb3B0aW9ucy5tb2NrVXNlclRva2VuYCBpcyB0aGUgbW9jayBhdXRoXG4gKiB0b2tlbiB0byB1c2UgZm9yIHVuaXQgdGVzdGluZyBTZWN1cml0eSBSdWxlcy5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3RTdG9yYWdlRW11bGF0b3IoXG4gIHN0b3JhZ2U6IEZpcmViYXNlU3RvcmFnZSxcbiAgaG9zdDogc3RyaW5nLFxuICBwb3J0OiBudW1iZXIsXG4gIG9wdGlvbnM6IHtcbiAgICBtb2NrVXNlclRva2VuPzogRW11bGF0b3JNb2NrVG9rZW5PcHRpb25zIHwgc3RyaW5nO1xuICB9ID0ge31cbik6IHZvaWQge1xuICBjb25uZWN0RW11bGF0b3JJbnRlcm5hbChzdG9yYWdlIGFzIEZpcmViYXNlU3RvcmFnZUltcGwsIGhvc3QsIHBvcnQsIG9wdGlvbnMpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFN0b3JhZ2VSZWZlcmVuY2UgfSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBSZWZlcmVuY2UsIGdldFN0cmVhbUludGVybmFsIH0gZnJvbSAnLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vKipcbiAqIERvd25sb2FkcyB0aGUgZGF0YSBhdCB0aGUgb2JqZWN0J3MgbG9jYXRpb24uIFJldHVybnMgYW4gZXJyb3IgaWYgdGhlIG9iamVjdFxuICogaXMgbm90IGZvdW5kLlxuICpcbiAqIFRvIHVzZSB0aGlzIGZ1bmN0aW9uYWxpdHksIHlvdSBoYXZlIHRvIHdoaXRlbGlzdCB5b3VyIGFwcCdzIG9yaWdpbiBpbiB5b3VyXG4gKiBDbG91ZCBTdG9yYWdlIGJ1Y2tldC4gU2VlIGFsc29cbiAqIGh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zdG9yYWdlL2RvY3MvY29uZmlndXJpbmctY29yc1xuICpcbiAqIFRoaXMgQVBJIGlzIG5vdCBhdmFpbGFibGUgaW4gTm9kZS5cbiAqXG4gKiBAcHVibGljXG4gKiBAcGFyYW0gcmVmIC0gU3RvcmFnZVJlZmVyZW5jZSB3aGVyZSBkYXRhIHNob3VsZCBiZSBkb3dubG9hZGVkLlxuICogQHBhcmFtIG1heERvd25sb2FkU2l6ZUJ5dGVzIC0gSWYgc2V0LCB0aGUgbWF4aW11bSBhbGxvd2VkIHNpemUgaW4gYnl0ZXMgdG9cbiAqIHJldHJpZXZlLlxuICogQHJldHVybnMgQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhIEJsb2IgY29udGFpbmluZyB0aGUgb2JqZWN0J3MgYnl0ZXNcbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuZXhwb3J0IGZ1bmN0aW9uIGdldEJsb2IoXG4gIHJlZjogU3RvcmFnZVJlZmVyZW5jZSxcbiAgbWF4RG93bmxvYWRTaXplQnl0ZXM/OiBudW1iZXJcbik6IFByb21pc2U8QmxvYj4ge1xuICB0aHJvdyBuZXcgRXJyb3IoJ2dldEJsb2IoKSBpcyBvbmx5IGF2YWlsYWJsZSBpbiBCcm93c2VyLWxpa2UgZW52aXJvbm1lbnRzJyk7XG59XG5cbi8qKlxuICogRG93bmxvYWRzIHRoZSBkYXRhIGF0IHRoZSBvYmplY3QncyBsb2NhdGlvbi4gUmFpc2VzIGFuIGVycm9yIGV2ZW50IGlmIHRoZVxuICogb2JqZWN0IGlzIG5vdCBmb3VuZC5cbiAqXG4gKiBUaGlzIEFQSSBpcyBvbmx5IGF2YWlsYWJsZSBpbiBOb2RlLlxuICpcbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSByZWYgLSBTdG9yYWdlUmVmZXJlbmNlIHdoZXJlIGRhdGEgc2hvdWxkIGJlIGRvd25sb2FkZWQuXG4gKiBAcGFyYW0gbWF4RG93bmxvYWRTaXplQnl0ZXMgLSBJZiBzZXQsIHRoZSBtYXhpbXVtIGFsbG93ZWQgc2l6ZSBpbiBieXRlcyB0b1xuICogcmV0cmlldmUuXG4gKiBAcmV0dXJucyBBIHN0cmVhbSB3aXRoIHRoZSBvYmplY3QncyBkYXRhIGFzIGJ5dGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdHJlYW0oXG4gIHJlZjogU3RvcmFnZVJlZmVyZW5jZSxcbiAgbWF4RG93bmxvYWRTaXplQnl0ZXM/OiBudW1iZXJcbik6IFJlYWRhYmxlU3RyZWFtIHtcbiAgcmVmID0gZ2V0TW9kdWxhckluc3RhbmNlKHJlZik7XG4gIHJldHVybiBnZXRTdHJlYW1JbnRlcm5hbChyZWYgYXMgUmVmZXJlbmNlLCBtYXhEb3dubG9hZFNpemVCeXRlcyk7XG59XG4iLCAiLyoqXG4gKiBDbG91ZCBTdG9yYWdlIGZvciBGaXJlYmFzZVxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5cbi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB7XG4gIF9yZWdpc3RlckNvbXBvbmVudCxcbiAgcmVnaXN0ZXJWZXJzaW9uLFxuICBTREtfVkVSU0lPTlxufSBmcm9tICdAZmlyZWJhc2UvYXBwJztcblxuaW1wb3J0IHsgRmlyZWJhc2VTdG9yYWdlSW1wbCB9IGZyb20gJy4vc2VydmljZSc7XG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIENvbXBvbmVudFR5cGUsXG4gIENvbXBvbmVudENvbnRhaW5lcixcbiAgSW5zdGFuY2VGYWN0b3J5T3B0aW9uc1xufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcblxuaW1wb3J0IHsgbmFtZSwgdmVyc2lvbiB9IGZyb20gJy4uL3BhY2thZ2UuanNvbic7XG5cbmltcG9ydCB7IEZpcmViYXNlU3RvcmFnZSB9IGZyb20gJy4vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IFNUT1JBR0VfVFlQRSB9IGZyb20gJy4vY29uc3RhbnRzJztcblxuZXhwb3J0ICogZnJvbSAnLi9hcGknO1xuZXhwb3J0ICogZnJvbSAnLi9hcGkubm9kZSc7XG5cbmZ1bmN0aW9uIGZhY3RvcnkoXG4gIGNvbnRhaW5lcjogQ29tcG9uZW50Q29udGFpbmVyLFxuICB7IGluc3RhbmNlSWRlbnRpZmllcjogdXJsIH06IEluc3RhbmNlRmFjdG9yeU9wdGlvbnNcbik6IEZpcmViYXNlU3RvcmFnZSB7XG4gIGNvbnN0IGFwcCA9IGNvbnRhaW5lci5nZXRQcm92aWRlcignYXBwJykuZ2V0SW1tZWRpYXRlKCk7XG4gIGNvbnN0IGF1dGhQcm92aWRlciA9IGNvbnRhaW5lci5nZXRQcm92aWRlcignYXV0aC1pbnRlcm5hbCcpO1xuICBjb25zdCBhcHBDaGVja1Byb3ZpZGVyID0gY29udGFpbmVyLmdldFByb3ZpZGVyKCdhcHAtY2hlY2staW50ZXJuYWwnKTtcblxuICByZXR1cm4gbmV3IEZpcmViYXNlU3RvcmFnZUltcGwoXG4gICAgYXBwLFxuICAgIGF1dGhQcm92aWRlcixcbiAgICBhcHBDaGVja1Byb3ZpZGVyLFxuICAgIHVybCxcbiAgICBTREtfVkVSU0lPTlxuICApO1xufVxuXG5mdW5jdGlvbiByZWdpc3RlclN0b3JhZ2UoKTogdm9pZCB7XG4gIF9yZWdpc3RlckNvbXBvbmVudChcbiAgICBuZXcgQ29tcG9uZW50KFxuICAgICAgU1RPUkFHRV9UWVBFLFxuICAgICAgZmFjdG9yeSxcbiAgICAgIENvbXBvbmVudFR5cGUuUFVCTElDXG4gICAgKS5zZXRNdWx0aXBsZUluc3RhbmNlcyh0cnVlKVxuICApO1xuXG4gIHJlZ2lzdGVyVmVyc2lvbihuYW1lLCB2ZXJzaW9uKTtcbn1cblxucmVnaXN0ZXJTdG9yYWdlKCk7XG4iLCAiZXhwb3J0ICogZnJvbSAnQGZpcmViYXNlL3N0b3JhZ2UnO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXgubWpzLm1hcFxuIiwgIi8qKlxuICogRmlyZWJhc2UgQ29uZmlndXJhdGlvbiBmb3IgT2JzaWRpYW4gUGx1Z2luXG4gKi9cblxuaW1wb3J0IHsgaW5pdGlhbGl6ZUFwcCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBnZXRBdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXV0aCc7XG5pbXBvcnQgeyBnZXRGdW5jdGlvbnMgfSBmcm9tICdmaXJlYmFzZS9mdW5jdGlvbnMnO1xuaW1wb3J0IHsgZ2V0U3RvcmFnZSB9IGZyb20gJ2ZpcmViYXNlL3N0b3JhZ2UnO1xuXG5jb25zdCBmaXJlYmFzZUNvbmZpZyA9IHtcbiAgYXBpS2V5OiBcIkFJemFTeURfcUgtMEdyX3BkbU5MT1FXNXBlYTJCYml5SHB4c3ROOFwiLFxuICBhdXRoRG9tYWluOiBcInV1dS1nbC5maXJlYmFzZWFwcC5jb21cIixcbiAgcHJvamVjdElkOiBcInV1dS1nbFwiLFxuICBzdG9yYWdlQnVja2V0OiBcInV1dS1nbC5maXJlYmFzZXN0b3JhZ2UuYXBwXCIsXG4gIG1lc3NhZ2luZ1NlbmRlcklkOiBcIjQ4NDU3MTcxNjAyMVwiLFxuICBhcHBJZDogXCIxOjQ4NDU3MTcxNjAyMTp3ZWI6MjVjYTM3YmY5MGYzMjBjZjA3YTFmY1wiXG59O1xuXG5leHBvcnQgY29uc3QgYXBwID0gaW5pdGlhbGl6ZUFwcChmaXJlYmFzZUNvbmZpZyk7XG5leHBvcnQgY29uc3QgYXV0aCA9IGdldEF1dGgoYXBwKTtcbmV4cG9ydCBjb25zdCBmdW5jdGlvbnMgPSBnZXRGdW5jdGlvbnMoYXBwLCAndXMtY2VudHJhbDEnKTtcbmV4cG9ydCBjb25zdCBzdG9yYWdlID0gZ2V0U3RvcmFnZShhcHApO1xuIiwgIi8qKlxuICogRmluZ2VycHJpbnRKUyB2NS4wLjEgLSBDb3B5cmlnaHQgKGMpIEZpbmdlcnByaW50SlMsIEluYywgMjAyNSAoaHR0cHM6Ly9maW5nZXJwcmludC5jb20pXG4gKlxuICogTGljZW5zZWQgdW5kZXIgTUlUIExpY2Vuc2VcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjUgRmluZ2VycHJpbnRKUywgSW5jXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICogb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuICogY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAqIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gKiBTT0ZUV0FSRS5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbnZhciB2ZXJzaW9uID0gXCI1LjAuMVwiO1xuXG5mdW5jdGlvbiB3YWl0KGR1cmF0aW9uTXMsIHJlc29sdmVXaXRoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGR1cmF0aW9uTXMsIHJlc29sdmVXaXRoKSk7XG59XG4vKipcbiAqIEFsbG93cyBhc3luY2hyb25vdXMgYWN0aW9ucyBhbmQgbWljcm90YXNrcyB0byBoYXBwZW4uXG4gKi9cbmZ1bmN0aW9uIHJlbGVhc2VFdmVudExvb3AoKSB7XG4gICAgLy8gRG9uJ3QgdXNlIHNldFRpbWVvdXQgYmVjYXVzZSBDaHJvbWUgdGhyb3R0bGVzIGl0IGluIHNvbWUgY2FzZXMgY2F1c2luZyB2ZXJ5IGxvbmcgYWdlbnQgZXhlY3V0aW9uOlxuICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS82MDMyNTkxLzExMTg3MDlcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vY2hyb21pdW0vY2hyb21pdW0vY29tbWl0LzAyOTVkZDA5NDk2MzMwZjNhOTEwM2VmN2U1NDNmYTliNjA1MDQwOWJcbiAgICAvLyBSZXVzaW5nIGEgTWVzc2FnZUNoYW5uZWwgb2JqZWN0IGdpdmVzIG5vIG5vdGljZWFibGUgYmVuZWZpdHNcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpO1xuICAgICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9ICgpID0+IHJlc29sdmUoKTtcbiAgICAgICAgY2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZShudWxsKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIHJlcXVlc3RJZGxlQ2FsbGJhY2tJZkF2YWlsYWJsZShmYWxsYmFja1RpbWVvdXQsIGRlYWRsaW5lVGltZW91dCA9IEluZmluaXR5KSB7XG4gICAgY29uc3QgeyByZXF1ZXN0SWRsZUNhbGxiYWNrIH0gPSB3aW5kb3c7XG4gICAgaWYgKHJlcXVlc3RJZGxlQ2FsbGJhY2spIHtcbiAgICAgICAgLy8gVGhlIGZ1bmN0aW9uIGByZXF1ZXN0SWRsZUNhbGxiYWNrYCBsb3NlcyB0aGUgYmluZGluZyB0byBgd2luZG93YCBoZXJlLlxuICAgICAgICAvLyBgZ2xvYmFsVGhpc2AgaXNuJ3QgYWx3YXlzIGVxdWFsIGB3aW5kb3dgIChzZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9pc3N1ZXMvNjgzKS5cbiAgICAgICAgLy8gVGhlcmVmb3JlLCBhbiBlcnJvciBjYW4gb2NjdXIuIGBjYWxsKHdpbmRvdyxgIHByZXZlbnRzIHRoZSBlcnJvci5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiByZXF1ZXN0SWRsZUNhbGxiYWNrLmNhbGwod2luZG93LCAoKSA9PiByZXNvbHZlKCksIHsgdGltZW91dDogZGVhZGxpbmVUaW1lb3V0IH0pKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB3YWl0KE1hdGgubWluKGZhbGxiYWNrVGltZW91dCwgZGVhZGxpbmVUaW1lb3V0KSk7XG4gICAgfVxufVxuZnVuY3Rpb24gaXNQcm9taXNlKHZhbHVlKSB7XG4gICAgcmV0dXJuICEhdmFsdWUgJiYgdHlwZW9mIHZhbHVlLnRoZW4gPT09ICdmdW5jdGlvbic7XG59XG4vKipcbiAqIENhbGxzIGEgbWF5YmUgYXN5bmNocm9ub3VzIGZ1bmN0aW9uIHdpdGhvdXQgY3JlYXRpbmcgbWljcm90YXNrcyB3aGVuIHRoZSBmdW5jdGlvbiBpcyBzeW5jaHJvbm91cy5cbiAqIENhdGNoZXMgZXJyb3JzIGluIGJvdGggY2FzZXMuXG4gKlxuICogSWYganVzdCB5b3UgcnVuIGEgY29kZSBsaWtlIHRoaXM6XG4gKiBgYGBcbiAqIGNvbnNvbGUudGltZSgnQWN0aW9uIGR1cmF0aW9uJylcbiAqIGF3YWl0IGFjdGlvbigpXG4gKiBjb25zb2xlLnRpbWVFbmQoJ0FjdGlvbiBkdXJhdGlvbicpXG4gKiBgYGBcbiAqIFRoZSBzeW5jaHJvbm91cyBmdW5jdGlvbiB0aW1lIGNhbiBiZSBtZWFzdXJlZCBpbmNvcnJlY3RseSBiZWNhdXNlIGFub3RoZXIgbWljcm90YXNrIG1heSBydW4gYmVmb3JlIHRoZSBgYXdhaXRgXG4gKiByZXR1cm5zIHRoZSBjb250cm9sIGJhY2sgdG8gdGhlIGNvZGUuXG4gKi9cbmZ1bmN0aW9uIGF3YWl0SWZBc3luYyhhY3Rpb24sIGNhbGxiYWNrKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmV0dXJuZWRWYWx1ZSA9IGFjdGlvbigpO1xuICAgICAgICBpZiAoaXNQcm9taXNlKHJldHVybmVkVmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm5lZFZhbHVlLnRoZW4oKHJlc3VsdCkgPT4gY2FsbGJhY2sodHJ1ZSwgcmVzdWx0KSwgKGVycm9yKSA9PiBjYWxsYmFjayhmYWxzZSwgZXJyb3IpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRydWUsIHJldHVybmVkVmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICBjYWxsYmFjayhmYWxzZSwgZXJyb3IpO1xuICAgIH1cbn1cbi8qKlxuICogSWYgeW91IHJ1biBtYW55IHN5bmNocm9ub3VzIHRhc2tzIHdpdGhvdXQgdXNpbmcgdGhpcyBmdW5jdGlvbiwgdGhlIEpTIG1haW4gbG9vcCB3aWxsIGJlIGJ1c3kgYW5kIGFzeW5jaHJvbm91cyB0YXNrc1xuICogKGUuZy4gY29tcGxldGluZyBhIG5ldHdvcmsgcmVxdWVzdCwgcmVuZGVyaW5nIHRoZSBwYWdlKSB3b24ndCBiZSBhYmxlIHRvIGhhcHBlbi5cbiAqIFRoaXMgZnVuY3Rpb24gYWxsb3dzIHJ1bm5pbmcgbWFueSBzeW5jaHJvbm91cyB0YXNrcyBzdWNoIHdheSB0aGF0IGFzeW5jaHJvbm91cyB0YXNrcyBjYW4gcnVuIHRvbyBpbiBiYWNrZ3JvdW5kLlxuICovXG5hc3luYyBmdW5jdGlvbiBtYXBXaXRoQnJlYWtzKGl0ZW1zLCBjYWxsYmFjaywgbG9vcFJlbGVhc2VJbnRlcnZhbCA9IDE2KSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IEFycmF5KGl0ZW1zLmxlbmd0aCk7XG4gICAgbGV0IGxhc3RMb29wUmVsZWFzZVRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgcmVzdWx0c1tpXSA9IGNhbGxiYWNrKGl0ZW1zW2ldLCBpKTtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYgKG5vdyA+PSBsYXN0TG9vcFJlbGVhc2VUaW1lICsgbG9vcFJlbGVhc2VJbnRlcnZhbCkge1xuICAgICAgICAgICAgbGFzdExvb3BSZWxlYXNlVGltZSA9IG5vdztcbiAgICAgICAgICAgIGF3YWl0IHJlbGVhc2VFdmVudExvb3AoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cztcbn1cbi8qKlxuICogTWFrZXMgdGhlIGdpdmVuIHByb21pc2UgbmV2ZXIgZW1pdCBhbiB1bmhhbmRsZWQgcHJvbWlzZSByZWplY3Rpb24gY29uc29sZSB3YXJuaW5nLlxuICogVGhlIHByb21pc2Ugd2lsbCBzdGlsbCBwYXNzIGVycm9ycyB0byB0aGUgbmV4dCBwcm9taXNlcy5cbiAqIFJldHVybnMgdGhlIGlucHV0IHByb21pc2UgZm9yIGNvbnZlbmllbmNlLlxuICpcbiAqIE90aGVyd2lzZSwgcHJvbWlzZSBlbWl0cyBhIGNvbnNvbGUgd2FybmluZyB1bmxlc3MgaXQgaGFzIGEgYGNhdGNoYCBsaXN0ZW5lci5cbiAqL1xuZnVuY3Rpb24gc3VwcHJlc3NVbmhhbmRsZWRSZWplY3Rpb25XYXJuaW5nKHByb21pc2UpIHtcbiAgICBwcm9taXNlLnRoZW4odW5kZWZpbmVkLCAoKSA9PiB1bmRlZmluZWQpO1xuICAgIHJldHVybiBwcm9taXNlO1xufVxuXG4vKlxuICogVGhpcyBmaWxlIGNvbnRhaW5zIGZ1bmN0aW9ucyB0byB3b3JrIHdpdGggcHVyZSBkYXRhIG9ubHkgKG5vIGJyb3dzZXIgZmVhdHVyZXMsIERPTSwgc2lkZSBlZmZlY3RzLCBldGMpLlxuICovXG4vKipcbiAqIERvZXMgdGhlIHNhbWUgYXMgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzIGJ1dCBoYXMgYmV0dGVyIHR5cGluZ1xuICovXG5mdW5jdGlvbiBpbmNsdWRlcyhoYXlzdGFjaywgbmVlZGxlKSB7XG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBoYXlzdGFjay5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgaWYgKGhheXN0YWNrW2ldID09PSBuZWVkbGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogTGlrZSBgIWluY2x1ZGVzKClgIGJ1dCB3aXRoIHByb3BlciB0eXBpbmdcbiAqL1xuZnVuY3Rpb24gZXhjbHVkZXMoaGF5c3RhY2ssIG5lZWRsZSkge1xuICAgIHJldHVybiAhaW5jbHVkZXMoaGF5c3RhY2ssIG5lZWRsZSk7XG59XG4vKipcbiAqIEJlIGNhcmVmdWwsIE5hTiBjYW4gcmV0dXJuXG4gKi9cbmZ1bmN0aW9uIHRvSW50KHZhbHVlKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHZhbHVlKTtcbn1cbi8qKlxuICogQmUgY2FyZWZ1bCwgTmFOIGNhbiByZXR1cm5cbiAqL1xuZnVuY3Rpb24gdG9GbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKTtcbn1cbmZ1bmN0aW9uIHJlcGxhY2VOYU4odmFsdWUsIHJlcGxhY2VtZW50KSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgaXNOYU4odmFsdWUpID8gcmVwbGFjZW1lbnQgOiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIGNvdW50VHJ1dGh5KHZhbHVlcykge1xuICAgIHJldHVybiB2YWx1ZXMucmVkdWNlKChzdW0sIHZhbHVlKSA9PiBzdW0gKyAodmFsdWUgPyAxIDogMCksIDApO1xufVxuZnVuY3Rpb24gcm91bmQodmFsdWUsIGJhc2UgPSAxKSB7XG4gICAgaWYgKE1hdGguYWJzKGJhc2UpID49IDEpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodmFsdWUgLyBiYXNlKSAqIGJhc2U7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICAvLyBTb21ldGltZXMgd2hlbiBhIG51bWJlciBpcyBtdWx0aXBsaWVkIGJ5IGEgc21hbGwgbnVtYmVyLCBwcmVjaXNpb24gaXMgbG9zdCxcbiAgICAgICAgLy8gZm9yIGV4YW1wbGUgMTIzNCAqIDAuMDAwMSA9PT0gMC4xMjM0MDAwMDAwMDAwMDAwMSwgYW5kIGl0J3MgbW9yZSBwcmVjaXNlIGRpdmlkZTogMTIzNCAvICgxIC8gMC4wMDAxKSA9PT0gMC4xMjM0LlxuICAgICAgICBjb25zdCBjb3VudGVyQmFzZSA9IDEgLyBiYXNlO1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIGNvdW50ZXJCYXNlKSAvIGNvdW50ZXJCYXNlO1xuICAgIH1cbn1cbi8qKlxuICogUGFyc2VzIGEgQ1NTIHNlbGVjdG9yIGludG8gdGFnIG5hbWUgd2l0aCBIVE1MIGF0dHJpYnV0ZXMuXG4gKiBPbmx5IHNpbmdsZSBlbGVtZW50IHNlbGVjdG9yIGFyZSBzdXBwb3J0ZWQgKHdpdGhvdXQgb3BlcmF0b3JzIGxpa2Ugc3BhY2UsICssID4sIGV0YykuXG4gKlxuICogTXVsdGlwbGUgdmFsdWVzIGNhbiBiZSByZXR1cm5lZCBmb3IgZWFjaCBhdHRyaWJ1dGUuIFlvdSBkZWNpZGUgaG93IHRvIGhhbmRsZSB0aGVtLlxuICovXG5mdW5jdGlvbiBwYXJzZVNpbXBsZUNzc1NlbGVjdG9yKHNlbGVjdG9yKSB7XG4gICAgdmFyIF9hLCBfYjtcbiAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSBgVW5leHBlY3RlZCBzeW50YXggJyR7c2VsZWN0b3J9J2A7XG4gICAgY29uc3QgdGFnTWF0Y2ggPSAvXlxccyooW2Etei1dKikoLiopJC9pLmV4ZWMoc2VsZWN0b3IpO1xuICAgIGNvbnN0IHRhZyA9IHRhZ01hdGNoWzFdIHx8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBhdHRyaWJ1dGVzID0ge307XG4gICAgY29uc3QgcGFydHNSZWdleCA9IC8oWy46I11bXFx3LV0rfFxcWy4rP1xcXSkvZ2k7XG4gICAgY29uc3QgYWRkQXR0cmlidXRlID0gKG5hbWUsIHZhbHVlKSA9PiB7XG4gICAgICAgIGF0dHJpYnV0ZXNbbmFtZV0gPSBhdHRyaWJ1dGVzW25hbWVdIHx8IFtdO1xuICAgICAgICBhdHRyaWJ1dGVzW25hbWVdLnB1c2godmFsdWUpO1xuICAgIH07XG4gICAgZm9yICg7Oykge1xuICAgICAgICBjb25zdCBtYXRjaCA9IHBhcnRzUmVnZXguZXhlYyh0YWdNYXRjaFsyXSk7XG4gICAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhcnQgPSBtYXRjaFswXTtcbiAgICAgICAgc3dpdGNoIChwYXJ0WzBdKSB7XG4gICAgICAgICAgICBjYXNlICcuJzpcbiAgICAgICAgICAgICAgICBhZGRBdHRyaWJ1dGUoJ2NsYXNzJywgcGFydC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICcjJzpcbiAgICAgICAgICAgICAgICBhZGRBdHRyaWJ1dGUoJ2lkJywgcGFydC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdbJzoge1xuICAgICAgICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZU1hdGNoID0gL15cXFsoW1xcdy1dKykoW358XiQqXT89KFwiKC4qPylcInwoW1xcdy1dKykpKT8oXFxzK1tpc10pP1xcXSQvLmV4ZWMocGFydCk7XG4gICAgICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZU1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZEF0dHJpYnV0ZShhdHRyaWJ1dGVNYXRjaFsxXSwgKF9iID0gKF9hID0gYXR0cmlidXRlTWF0Y2hbNF0pICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IGF0dHJpYnV0ZU1hdGNoWzVdKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiAnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBbdGFnLCBhdHRyaWJ1dGVzXTtcbn1cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgdG8gVVRGOCBieXRlc1xuICovXG5mdW5jdGlvbiBnZXRVVEY4Qnl0ZXMoaW5wdXQpIHtcbiAgICAvLyBCZW5jaG1hcms6IGh0dHBzOi8vanNiZW5jaC5tZS9iNmtsYWF4Z3dxLzFcbiAgICAvLyBJZiB5b3Ugd2FudCB0byBqdXN0IGNvdW50IGJ5dGVzLCBzZWUgc29sdXRpb25zIGF0IGh0dHBzOi8vanNiZW5jaC5tZS9laGtsYWI0MTVlLzFcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShpbnB1dC5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgLy8gYGNoYXJDb2RlYCBpcyBmYXN0ZXIgdGhhbiBlbmNvZGluZywgc28gd2UgcHJlZmVyIHRoYXQgd2hlbiBpdCdzIHBvc3NpYmxlXG4gICAgICAgIGNvbnN0IGNoYXJDb2RlID0gaW5wdXQuY2hhckNvZGVBdChpKTtcbiAgICAgICAgLy8gSW4gY2FzZSBvZiBub24tQVNDSUkgc3ltYm9scyB3ZSB1c2UgcHJvcGVyIGVuY29kaW5nXG4gICAgICAgIGlmIChjaGFyQ29kZSA+IDEyNykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShpbnB1dCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0W2ldID0gY2hhckNvZGU7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qXG4gKiBCYXNlZCBvbiBodHRwczovL2dpdGh1Yi5jb20va2FyYW5seW9ucy9tdXJtdXJIYXNoMy5qcy9ibG9iL2EzM2QwNzIzMTI3ZTJlNTQxNTA1NmM0NTVmOGFlZDI0NTFhY2UyMDgvbXVybXVySGFzaDMuanNcbiAqL1xuLyoqXG4gKiBBZGRzIHR3byA2NC1iaXQgdmFsdWVzIChwcm92aWRlZCBhcyB0dXBsZXMgb2YgMzItYml0IHZhbHVlcylcbiAqIGFuZCB1cGRhdGVzIChtdXRhdGVzKSBmaXJzdCB2YWx1ZSB0byB3cml0ZSB0aGUgcmVzdWx0XG4gKi9cbmZ1bmN0aW9uIHg2NEFkZChtLCBuKSB7XG4gICAgY29uc3QgbTAgPSBtWzBdID4+PiAxNiwgbTEgPSBtWzBdICYgMHhmZmZmLCBtMiA9IG1bMV0gPj4+IDE2LCBtMyA9IG1bMV0gJiAweGZmZmY7XG4gICAgY29uc3QgbjAgPSBuWzBdID4+PiAxNiwgbjEgPSBuWzBdICYgMHhmZmZmLCBuMiA9IG5bMV0gPj4+IDE2LCBuMyA9IG5bMV0gJiAweGZmZmY7XG4gICAgbGV0IG8wID0gMCwgbzEgPSAwLCBvMiA9IDAsIG8zID0gMDtcbiAgICBvMyArPSBtMyArIG4zO1xuICAgIG8yICs9IG8zID4+PiAxNjtcbiAgICBvMyAmPSAweGZmZmY7XG4gICAgbzIgKz0gbTIgKyBuMjtcbiAgICBvMSArPSBvMiA+Pj4gMTY7XG4gICAgbzIgJj0gMHhmZmZmO1xuICAgIG8xICs9IG0xICsgbjE7XG4gICAgbzAgKz0gbzEgPj4+IDE2O1xuICAgIG8xICY9IDB4ZmZmZjtcbiAgICBvMCArPSBtMCArIG4wO1xuICAgIG8wICY9IDB4ZmZmZjtcbiAgICBtWzBdID0gKG8wIDw8IDE2KSB8IG8xO1xuICAgIG1bMV0gPSAobzIgPDwgMTYpIHwgbzM7XG59XG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIDY0LWJpdCB2YWx1ZXMgKHByb3ZpZGVkIGFzIHR1cGxlcyBvZiAzMi1iaXQgdmFsdWVzKVxuICogYW5kIHVwZGF0ZXMgKG11dGF0ZXMpIGZpcnN0IHZhbHVlIHRvIHdyaXRlIHRoZSByZXN1bHRcbiAqL1xuZnVuY3Rpb24geDY0TXVsdGlwbHkobSwgbikge1xuICAgIGNvbnN0IG0wID0gbVswXSA+Pj4gMTYsIG0xID0gbVswXSAmIDB4ZmZmZiwgbTIgPSBtWzFdID4+PiAxNiwgbTMgPSBtWzFdICYgMHhmZmZmO1xuICAgIGNvbnN0IG4wID0gblswXSA+Pj4gMTYsIG4xID0gblswXSAmIDB4ZmZmZiwgbjIgPSBuWzFdID4+PiAxNiwgbjMgPSBuWzFdICYgMHhmZmZmO1xuICAgIGxldCBvMCA9IDAsIG8xID0gMCwgbzIgPSAwLCBvMyA9IDA7XG4gICAgbzMgKz0gbTMgKiBuMztcbiAgICBvMiArPSBvMyA+Pj4gMTY7XG4gICAgbzMgJj0gMHhmZmZmO1xuICAgIG8yICs9IG0yICogbjM7XG4gICAgbzEgKz0gbzIgPj4+IDE2O1xuICAgIG8yICY9IDB4ZmZmZjtcbiAgICBvMiArPSBtMyAqIG4yO1xuICAgIG8xICs9IG8yID4+PiAxNjtcbiAgICBvMiAmPSAweGZmZmY7XG4gICAgbzEgKz0gbTEgKiBuMztcbiAgICBvMCArPSBvMSA+Pj4gMTY7XG4gICAgbzEgJj0gMHhmZmZmO1xuICAgIG8xICs9IG0yICogbjI7XG4gICAgbzAgKz0gbzEgPj4+IDE2O1xuICAgIG8xICY9IDB4ZmZmZjtcbiAgICBvMSArPSBtMyAqIG4xO1xuICAgIG8wICs9IG8xID4+PiAxNjtcbiAgICBvMSAmPSAweGZmZmY7XG4gICAgbzAgKz0gbTAgKiBuMyArIG0xICogbjIgKyBtMiAqIG4xICsgbTMgKiBuMDtcbiAgICBvMCAmPSAweGZmZmY7XG4gICAgbVswXSA9IChvMCA8PCAxNikgfCBvMTtcbiAgICBtWzFdID0gKG8yIDw8IDE2KSB8IG8zO1xufVxuLyoqXG4gKiBQcm92aWRlcyBsZWZ0IHJvdGF0aW9uIG9mIHRoZSBnaXZlbiBpbnQ2NCB2YWx1ZSAocHJvdmlkZWQgYXMgdHVwbGUgb2YgdHdvIGludDMyKVxuICogYnkgZ2l2ZW4gbnVtYmVyIG9mIGJpdHMuIFJlc3VsdCBpcyB3cml0dGVuIGJhY2sgdG8gdGhlIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIHg2NFJvdGwobSwgYml0cykge1xuICAgIGNvbnN0IG0wID0gbVswXTtcbiAgICBiaXRzICU9IDY0O1xuICAgIGlmIChiaXRzID09PSAzMikge1xuICAgICAgICBtWzBdID0gbVsxXTtcbiAgICAgICAgbVsxXSA9IG0wO1xuICAgIH1cbiAgICBlbHNlIGlmIChiaXRzIDwgMzIpIHtcbiAgICAgICAgbVswXSA9IChtMCA8PCBiaXRzKSB8IChtWzFdID4+PiAoMzIgLSBiaXRzKSk7XG4gICAgICAgIG1bMV0gPSAobVsxXSA8PCBiaXRzKSB8IChtMCA+Pj4gKDMyIC0gYml0cykpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYml0cyAtPSAzMjtcbiAgICAgICAgbVswXSA9IChtWzFdIDw8IGJpdHMpIHwgKG0wID4+PiAoMzIgLSBiaXRzKSk7XG4gICAgICAgIG1bMV0gPSAobTAgPDwgYml0cykgfCAobVsxXSA+Pj4gKDMyIC0gYml0cykpO1xuICAgIH1cbn1cbi8qKlxuICogUHJvdmlkZXMgYSBsZWZ0IHNoaWZ0IG9mIHRoZSBnaXZlbiBpbnQzMiB2YWx1ZSAocHJvdmlkZWQgYXMgdHVwbGUgb2YgWzAsIGludDMyXSlcbiAqIGJ5IGdpdmVuIG51bWJlciBvZiBiaXRzLiBSZXN1bHQgaXMgd3JpdHRlbiBiYWNrIHRvIHRoZSB2YWx1ZVxuICovXG5mdW5jdGlvbiB4NjRMZWZ0U2hpZnQobSwgYml0cykge1xuICAgIGJpdHMgJT0gNjQ7XG4gICAgaWYgKGJpdHMgPT09IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBlbHNlIGlmIChiaXRzIDwgMzIpIHtcbiAgICAgICAgbVswXSA9IG1bMV0gPj4+ICgzMiAtIGJpdHMpO1xuICAgICAgICBtWzFdID0gbVsxXSA8PCBiaXRzO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgbVswXSA9IG1bMV0gPDwgKGJpdHMgLSAzMik7XG4gICAgICAgIG1bMV0gPSAwO1xuICAgIH1cbn1cbi8qKlxuICogUHJvdmlkZXMgYSBYT1Igb2YgdGhlIGdpdmVuIGludDY0IHZhbHVlcyhwcm92aWRlZCBhcyB0dXBsZSBvZiB0d28gaW50MzIpLlxuICogUmVzdWx0IGlzIHdyaXR0ZW4gYmFjayB0byB0aGUgZmlyc3QgdmFsdWVcbiAqL1xuZnVuY3Rpb24geDY0WG9yKG0sIG4pIHtcbiAgICBtWzBdIF49IG5bMF07XG4gICAgbVsxXSBePSBuWzFdO1xufVxuY29uc3QgRjEgPSBbMHhmZjUxYWZkNywgMHhlZDU1OGNjZF07XG5jb25zdCBGMiA9IFsweGM0Y2ViOWZlLCAweDFhODVlYzUzXTtcbi8qKlxuICogQ2FsY3VsYXRlcyBtdXJtdXJIYXNoMydzIGZpbmFsIHg2NCBtaXggb2YgdGhhdCBibG9jayBhbmQgd3JpdGVzIHJlc3VsdCBiYWNrIHRvIHRoZSBpbnB1dCB2YWx1ZS5cbiAqIChgWzAsIGhbMF0gPj4+IDFdYCBpcyBhIDMzIGJpdCB1bnNpZ25lZCByaWdodCBzaGlmdC4gVGhpcyBpcyB0aGVcbiAqIG9ubHkgcGxhY2Ugd2hlcmUgd2UgbmVlZCB0byByaWdodCBzaGlmdCA2NGJpdCBpbnRzLilcbiAqL1xuZnVuY3Rpb24geDY0Rm1peChoKSB7XG4gICAgY29uc3Qgc2hpZnRlZCA9IFswLCBoWzBdID4+PiAxXTtcbiAgICB4NjRYb3IoaCwgc2hpZnRlZCk7XG4gICAgeDY0TXVsdGlwbHkoaCwgRjEpO1xuICAgIHNoaWZ0ZWRbMV0gPSBoWzBdID4+PiAxO1xuICAgIHg2NFhvcihoLCBzaGlmdGVkKTtcbiAgICB4NjRNdWx0aXBseShoLCBGMik7XG4gICAgc2hpZnRlZFsxXSA9IGhbMF0gPj4+IDE7XG4gICAgeDY0WG9yKGgsIHNoaWZ0ZWQpO1xufVxuY29uc3QgQzEgPSBbMHg4N2MzN2I5MSwgMHgxMTQyNTNkNV07XG5jb25zdCBDMiA9IFsweDRjZjVhZDQzLCAweDI3NDU5MzdmXTtcbmNvbnN0IE0kMSA9IFswLCA1XTtcbmNvbnN0IE4xID0gWzAsIDB4NTJkY2U3MjldO1xuY29uc3QgTjIgPSBbMCwgMHgzODQ5NWFiNV07XG4vKipcbiAqIEdpdmVuIGEgc3RyaW5nIGFuZCBhbiBvcHRpb25hbCBzZWVkIGFzIGFuIGludCwgcmV0dXJucyBhIDEyOCBiaXRcbiAqIGhhc2ggdXNpbmcgdGhlIHg2NCBmbGF2b3Igb2YgTXVybXVySGFzaDMsIGFzIGFuIHVuc2lnbmVkIGhleC5cbiAqIEFsbCBpbnRlcm5hbCBmdW5jdGlvbnMgbXV0YXRlcyBwYXNzZWQgdmFsdWUgdG8gYWNoaWV2ZSBtaW5pbWFsIG1lbW9yeSBhbGxvY2F0aW9ucyBhbmQgR0MgbG9hZFxuICpcbiAqIEJlbmNobWFyayBodHRwczovL2pzYmVuY2gubWUvcDRsa3Bhb2FiaS8xXG4gKi9cbmZ1bmN0aW9uIHg2NGhhc2gxMjgoaW5wdXQsIHNlZWQpIHtcbiAgICBjb25zdCBrZXkgPSBnZXRVVEY4Qnl0ZXMoaW5wdXQpO1xuICAgIHNlZWQgPSBzZWVkIHx8IDA7XG4gICAgY29uc3QgbGVuZ3RoID0gWzAsIGtleS5sZW5ndGhdO1xuICAgIGNvbnN0IHJlbWFpbmRlciA9IGxlbmd0aFsxXSAlIDE2O1xuICAgIGNvbnN0IGJ5dGVzID0gbGVuZ3RoWzFdIC0gcmVtYWluZGVyO1xuICAgIGNvbnN0IGgxID0gWzAsIHNlZWRdO1xuICAgIGNvbnN0IGgyID0gWzAsIHNlZWRdO1xuICAgIGNvbnN0IGsxID0gWzAsIDBdO1xuICAgIGNvbnN0IGsyID0gWzAsIDBdO1xuICAgIGxldCBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBieXRlczsgaSA9IGkgKyAxNikge1xuICAgICAgICBrMVswXSA9IGtleVtpICsgNF0gfCAoa2V5W2kgKyA1XSA8PCA4KSB8IChrZXlbaSArIDZdIDw8IDE2KSB8IChrZXlbaSArIDddIDw8IDI0KTtcbiAgICAgICAgazFbMV0gPSBrZXlbaV0gfCAoa2V5W2kgKyAxXSA8PCA4KSB8IChrZXlbaSArIDJdIDw8IDE2KSB8IChrZXlbaSArIDNdIDw8IDI0KTtcbiAgICAgICAgazJbMF0gPSBrZXlbaSArIDEyXSB8IChrZXlbaSArIDEzXSA8PCA4KSB8IChrZXlbaSArIDE0XSA8PCAxNikgfCAoa2V5W2kgKyAxNV0gPDwgMjQpO1xuICAgICAgICBrMlsxXSA9IGtleVtpICsgOF0gfCAoa2V5W2kgKyA5XSA8PCA4KSB8IChrZXlbaSArIDEwXSA8PCAxNikgfCAoa2V5W2kgKyAxMV0gPDwgMjQpO1xuICAgICAgICB4NjRNdWx0aXBseShrMSwgQzEpO1xuICAgICAgICB4NjRSb3RsKGsxLCAzMSk7XG4gICAgICAgIHg2NE11bHRpcGx5KGsxLCBDMik7XG4gICAgICAgIHg2NFhvcihoMSwgazEpO1xuICAgICAgICB4NjRSb3RsKGgxLCAyNyk7XG4gICAgICAgIHg2NEFkZChoMSwgaDIpO1xuICAgICAgICB4NjRNdWx0aXBseShoMSwgTSQxKTtcbiAgICAgICAgeDY0QWRkKGgxLCBOMSk7XG4gICAgICAgIHg2NE11bHRpcGx5KGsyLCBDMik7XG4gICAgICAgIHg2NFJvdGwoazIsIDMzKTtcbiAgICAgICAgeDY0TXVsdGlwbHkoazIsIEMxKTtcbiAgICAgICAgeDY0WG9yKGgyLCBrMik7XG4gICAgICAgIHg2NFJvdGwoaDIsIDMxKTtcbiAgICAgICAgeDY0QWRkKGgyLCBoMSk7XG4gICAgICAgIHg2NE11bHRpcGx5KGgyLCBNJDEpO1xuICAgICAgICB4NjRBZGQoaDIsIE4yKTtcbiAgICB9XG4gICAgazFbMF0gPSAwO1xuICAgIGsxWzFdID0gMDtcbiAgICBrMlswXSA9IDA7XG4gICAgazJbMV0gPSAwO1xuICAgIGNvbnN0IHZhbCA9IFswLCAwXTtcbiAgICBzd2l0Y2ggKHJlbWFpbmRlcikge1xuICAgICAgICBjYXNlIDE1OlxuICAgICAgICAgICAgdmFsWzFdID0ga2V5W2kgKyAxNF07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCA0OCk7XG4gICAgICAgICAgICB4NjRYb3IoazIsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgMTQ6XG4gICAgICAgICAgICB2YWxbMV0gPSBrZXlbaSArIDEzXTtcbiAgICAgICAgICAgIHg2NExlZnRTaGlmdCh2YWwsIDQwKTtcbiAgICAgICAgICAgIHg2NFhvcihrMiwgdmFsKTtcbiAgICAgICAgLy8gZmFsbHRocm91Z2hcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgMTJdO1xuICAgICAgICAgICAgeDY0TGVmdFNoaWZ0KHZhbCwgMzIpO1xuICAgICAgICAgICAgeDY0WG9yKGsyLCB2YWwpO1xuICAgICAgICAvLyBmYWxsdGhyb3VnaFxuICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgICAgdmFsWzFdID0ga2V5W2kgKyAxMV07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCAyNCk7XG4gICAgICAgICAgICB4NjRYb3IoazIsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgICB2YWxbMV0gPSBrZXlbaSArIDEwXTtcbiAgICAgICAgICAgIHg2NExlZnRTaGlmdCh2YWwsIDE2KTtcbiAgICAgICAgICAgIHg2NFhvcihrMiwgdmFsKTtcbiAgICAgICAgLy8gZmFsbHRocm91Z2hcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgOV07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCA4KTtcbiAgICAgICAgICAgIHg2NFhvcihrMiwgdmFsKTtcbiAgICAgICAgLy8gZmFsbHRocm91Z2hcbiAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgdmFsWzFdID0ga2V5W2kgKyA4XTtcbiAgICAgICAgICAgIHg2NFhvcihrMiwgdmFsKTtcbiAgICAgICAgICAgIHg2NE11bHRpcGx5KGsyLCBDMik7XG4gICAgICAgICAgICB4NjRSb3RsKGsyLCAzMyk7XG4gICAgICAgICAgICB4NjRNdWx0aXBseShrMiwgQzEpO1xuICAgICAgICAgICAgeDY0WG9yKGgyLCBrMik7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgN107XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCA1Nik7XG4gICAgICAgICAgICB4NjRYb3IoazEsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgNl07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCA0OCk7XG4gICAgICAgICAgICB4NjRYb3IoazEsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgNV07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCA0MCk7XG4gICAgICAgICAgICB4NjRYb3IoazEsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgNF07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCAzMik7XG4gICAgICAgICAgICB4NjRYb3IoazEsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgM107XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCAyNCk7XG4gICAgICAgICAgICB4NjRYb3IoazEsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgMl07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCAxNik7XG4gICAgICAgICAgICB4NjRYb3IoazEsIHZhbCk7XG4gICAgICAgIC8vIGZhbGx0aHJvdWdoXG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHZhbFsxXSA9IGtleVtpICsgMV07XG4gICAgICAgICAgICB4NjRMZWZ0U2hpZnQodmFsLCA4KTtcbiAgICAgICAgICAgIHg2NFhvcihrMSwgdmFsKTtcbiAgICAgICAgLy8gZmFsbHRocm91Z2hcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgdmFsWzFdID0ga2V5W2ldO1xuICAgICAgICAgICAgeDY0WG9yKGsxLCB2YWwpO1xuICAgICAgICAgICAgeDY0TXVsdGlwbHkoazEsIEMxKTtcbiAgICAgICAgICAgIHg2NFJvdGwoazEsIDMxKTtcbiAgICAgICAgICAgIHg2NE11bHRpcGx5KGsxLCBDMik7XG4gICAgICAgICAgICB4NjRYb3IoaDEsIGsxKTtcbiAgICAgICAgLy8gZmFsbHRocm91Z2hcbiAgICB9XG4gICAgeDY0WG9yKGgxLCBsZW5ndGgpO1xuICAgIHg2NFhvcihoMiwgbGVuZ3RoKTtcbiAgICB4NjRBZGQoaDEsIGgyKTtcbiAgICB4NjRBZGQoaDIsIGgxKTtcbiAgICB4NjRGbWl4KGgxKTtcbiAgICB4NjRGbWl4KGgyKTtcbiAgICB4NjRBZGQoaDEsIGgyKTtcbiAgICB4NjRBZGQoaDIsIGgxKTtcbiAgICByZXR1cm4gKCgnMDAwMDAwMDAnICsgKGgxWzBdID4+PiAwKS50b1N0cmluZygxNikpLnNsaWNlKC04KSArXG4gICAgICAgICgnMDAwMDAwMDAnICsgKGgxWzFdID4+PiAwKS50b1N0cmluZygxNikpLnNsaWNlKC04KSArXG4gICAgICAgICgnMDAwMDAwMDAnICsgKGgyWzBdID4+PiAwKS50b1N0cmluZygxNikpLnNsaWNlKC04KSArXG4gICAgICAgICgnMDAwMDAwMDAnICsgKGgyWzFdID4+PiAwKS50b1N0cmluZygxNikpLnNsaWNlKC04KSk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYW4gZXJyb3Igb2JqZWN0IHRvIGEgcGxhaW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgd2l0aCBgSlNPTi5zdHJpbmdpZnlgLlxuICogSWYgeW91IGp1c3QgcnVuIGBKU09OLnN0cmluZ2lmeShlcnJvcilgLCB5b3UnbGwgZ2V0IGAne30nYC5cbiAqL1xuZnVuY3Rpb24gZXJyb3JUb09iamVjdChlcnJvcikge1xuICAgIHZhciBfYTtcbiAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBlcnJvci5uYW1lLFxuICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICBzdGFjazogKF9hID0gZXJyb3Iuc3RhY2spID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zcGxpdCgnXFxuJyksXG4gICAgICAgIC8vIFRoZSBmaWVsZHMgYXJlIG5vdCBlbnVtZXJhYmxlLCBzbyBUUyBpcyB3cm9uZyBzYXlpbmcgdGhhdCB0aGV5IHdpbGwgYmUgb3ZlcnJpZGRlblxuICAgICAgICAuLi5lcnJvcixcbiAgICB9O1xufVxuZnVuY3Rpb24gaXNGdW5jdGlvbk5hdGl2ZShmdW5jKSB7XG4gICAgcmV0dXJuIC9eZnVuY3Rpb25cXHMuKj9cXHtcXHMqXFxbbmF0aXZlIGNvZGVdXFxzKn0kLy50ZXN0KFN0cmluZyhmdW5jKSk7XG59XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbmZ1bmN0aW9uIGlzRmluYWxSZXN1bHRMb2FkZWQobG9hZFJlc3VsdCkge1xuICAgIHJldHVybiB0eXBlb2YgbG9hZFJlc3VsdCAhPT0gJ2Z1bmN0aW9uJztcbn1cbi8qKlxuICogTG9hZHMgdGhlIGdpdmVuIGVudHJvcHkgc291cmNlLiBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBnZXRzIGFuIGVudHJvcHkgY29tcG9uZW50IGZyb20gdGhlIHNvdXJjZS5cbiAqXG4gKiBUaGUgcmVzdWx0IGlzIHJldHVybmVkIHN5bmNocm9ub3VzbHkgdG8gcHJldmVudCBgbG9hZFNvdXJjZXNgIGZyb21cbiAqIHdhaXRpbmcgZm9yIG9uZSBzb3VyY2UgdG8gbG9hZCBiZWZvcmUgZ2V0dGluZyB0aGUgY29tcG9uZW50cyBmcm9tIHRoZSBvdGhlciBzb3VyY2VzLlxuICovXG5mdW5jdGlvbiBsb2FkU291cmNlKHNvdXJjZSwgc291cmNlT3B0aW9ucykge1xuICAgIGNvbnN0IHNvdXJjZUxvYWRQcm9taXNlID0gc3VwcHJlc3NVbmhhbmRsZWRSZWplY3Rpb25XYXJuaW5nKG5ldyBQcm9taXNlKChyZXNvbHZlTG9hZCkgPT4ge1xuICAgICAgICBjb25zdCBsb2FkU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgLy8gYGF3YWl0SWZBc3luY2AgaXMgdXNlZCBpbnN0ZWFkIG9mIGp1c3QgYGF3YWl0YCBpbiBvcmRlciB0byBtZWFzdXJlIHRoZSBkdXJhdGlvbiBvZiBzeW5jaHJvbm91cyBzb3VyY2VzXG4gICAgICAgIC8vIGNvcnJlY3RseSAob3RoZXIgbWljcm90YXNrcyB3b24ndCBhZmZlY3QgdGhlIGR1cmF0aW9uKS5cbiAgICAgICAgYXdhaXRJZkFzeW5jKHNvdXJjZS5iaW5kKG51bGwsIHNvdXJjZU9wdGlvbnMpLCAoLi4ubG9hZEFyZ3MpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxvYWREdXJhdGlvbiA9IERhdGUubm93KCkgLSBsb2FkU3RhcnRUaW1lO1xuICAgICAgICAgICAgLy8gU291cmNlIGxvYWRpbmcgZmFpbGVkXG4gICAgICAgICAgICBpZiAoIWxvYWRBcmdzWzBdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmVMb2FkKCgpID0+ICh7IGVycm9yOiBsb2FkQXJnc1sxXSwgZHVyYXRpb246IGxvYWREdXJhdGlvbiB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBsb2FkUmVzdWx0ID0gbG9hZEFyZ3NbMV07XG4gICAgICAgICAgICAvLyBTb3VyY2UgbG9hZGVkIHdpdGggdGhlIGZpbmFsIHJlc3VsdFxuICAgICAgICAgICAgaWYgKGlzRmluYWxSZXN1bHRMb2FkZWQobG9hZFJlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZUxvYWQoKCkgPT4gKHsgdmFsdWU6IGxvYWRSZXN1bHQsIGR1cmF0aW9uOiBsb2FkRHVyYXRpb24gfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gU291cmNlIGxvYWRlZCB3aXRoIFwiZ2V0XCIgc3RhZ2VcbiAgICAgICAgICAgIHJlc29sdmVMb2FkKCgpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlR2V0KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZ2V0U3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICBhd2FpdElmQXN5bmMobG9hZFJlc3VsdCwgKC4uLmdldEFyZ3MpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZHVyYXRpb24gPSBsb2FkRHVyYXRpb24gKyBEYXRlLm5vdygpIC0gZ2V0U3RhcnRUaW1lO1xuICAgICAgICAgICAgICAgICAgICAvLyBTb3VyY2UgZ2V0dGluZyBmYWlsZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFnZXRBcmdzWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZUdldCh7IGVycm9yOiBnZXRBcmdzWzFdLCBkdXJhdGlvbiB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBTb3VyY2UgZ2V0dGluZyBzdWNjZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZUdldCh7IHZhbHVlOiBnZXRBcmdzWzFdLCBkdXJhdGlvbiB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfSk7XG4gICAgfSkpO1xuICAgIHJldHVybiBmdW5jdGlvbiBnZXRDb21wb25lbnQoKSB7XG4gICAgICAgIHJldHVybiBzb3VyY2VMb2FkUHJvbWlzZS50aGVuKChmaW5hbGl6ZVNvdXJjZSkgPT4gZmluYWxpemVTb3VyY2UoKSk7XG4gICAgfTtcbn1cbi8qKlxuICogTG9hZHMgdGhlIGdpdmVuIGVudHJvcHkgc291cmNlcy4gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgY29sbGVjdHMgdGhlIGVudHJvcHkgY29tcG9uZW50cy5cbiAqXG4gKiBUaGUgcmVzdWx0IGlzIHJldHVybmVkIHN5bmNocm9ub3VzbHkgaW4gb3JkZXIgdG8gYWxsb3cgc3RhcnQgZ2V0dGluZyB0aGUgY29tcG9uZW50c1xuICogYmVmb3JlIHRoZSBzb3VyY2VzIGFyZSBsb2FkZWQgY29tcGxldGVseS5cbiAqXG4gKiBXYXJuaW5nIGZvciBwYWNrYWdlIHVzZXJzOlxuICogVGhpcyBmdW5jdGlvbiBpcyBvdXQgb2YgU2VtYW50aWMgVmVyc2lvbmluZywgaS5lLiBjYW4gY2hhbmdlIHVuZXhwZWN0ZWRseS4gVXNhZ2UgaXMgYXQgeW91ciBvd24gcmlzay5cbiAqL1xuZnVuY3Rpb24gbG9hZFNvdXJjZXMoc291cmNlcywgc291cmNlT3B0aW9ucywgZXhjbHVkZVNvdXJjZXMsIGxvb3BSZWxlYXNlSW50ZXJ2YWwpIHtcbiAgICBjb25zdCBpbmNsdWRlZFNvdXJjZXMgPSBPYmplY3Qua2V5cyhzb3VyY2VzKS5maWx0ZXIoKHNvdXJjZUtleSkgPT4gZXhjbHVkZXMoZXhjbHVkZVNvdXJjZXMsIHNvdXJjZUtleSkpO1xuICAgIC8vIFVzaW5nIGBtYXBXaXRoQnJlYWtzYCBhbGxvd3MgYXN5bmNocm9ub3VzIHNvdXJjZXMgdG8gY29tcGxldGUgYmV0d2VlbiBzeW5jaHJvbm91cyBzb3VyY2VzXG4gICAgLy8gYW5kIG1lYXN1cmUgdGhlIGR1cmF0aW9uIGNvcnJlY3RseVxuICAgIGNvbnN0IHNvdXJjZUdldHRlcnNQcm9taXNlID0gc3VwcHJlc3NVbmhhbmRsZWRSZWplY3Rpb25XYXJuaW5nKG1hcFdpdGhCcmVha3MoaW5jbHVkZWRTb3VyY2VzLCAoc291cmNlS2V5KSA9PiBsb2FkU291cmNlKHNvdXJjZXNbc291cmNlS2V5XSwgc291cmNlT3B0aW9ucyksIGxvb3BSZWxlYXNlSW50ZXJ2YWwpKTtcbiAgICByZXR1cm4gYXN5bmMgZnVuY3Rpb24gZ2V0Q29tcG9uZW50cygpIHtcbiAgICAgICAgY29uc3Qgc291cmNlR2V0dGVycyA9IGF3YWl0IHNvdXJjZUdldHRlcnNQcm9taXNlO1xuICAgICAgICBjb25zdCBjb21wb25lbnRQcm9taXNlcyA9IGF3YWl0IG1hcFdpdGhCcmVha3Moc291cmNlR2V0dGVycywgKHNvdXJjZUdldHRlcikgPT4gc3VwcHJlc3NVbmhhbmRsZWRSZWplY3Rpb25XYXJuaW5nKHNvdXJjZUdldHRlcigpKSwgbG9vcFJlbGVhc2VJbnRlcnZhbCk7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudEFycmF5ID0gYXdhaXQgUHJvbWlzZS5hbGwoY29tcG9uZW50UHJvbWlzZXMpO1xuICAgICAgICAvLyBLZWVwaW5nIHRoZSBjb21wb25lbnQga2V5cyBvcmRlciB0aGUgc2FtZSBhcyB0aGUgc291cmNlIGtleXMgb3JkZXJcbiAgICAgICAgY29uc3QgY29tcG9uZW50cyA9IHt9O1xuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5jbHVkZWRTb3VyY2VzLmxlbmd0aDsgKytpbmRleCkge1xuICAgICAgICAgICAgY29tcG9uZW50c1tpbmNsdWRlZFNvdXJjZXNbaW5kZXhdXSA9IGNvbXBvbmVudEFycmF5W2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcG9uZW50cztcbiAgICB9O1xufVxuLyoqXG4gKiBNb2RpZmllcyBhbiBlbnRyb3B5IHNvdXJjZSBieSB0cmFuc2Zvcm1pbmcgaXRzIHJldHVybmVkIHZhbHVlIHdpdGggdGhlIGdpdmVuIGZ1bmN0aW9uLlxuICogS2VlcHMgdGhlIHNvdXJjZSBwcm9wZXJ0aWVzOiBzeW5jL2FzeW5jLCAxLzIgc3RhZ2VzLlxuICpcbiAqIFdhcm5pbmcgZm9yIHBhY2thZ2UgdXNlcnM6XG4gKiBUaGlzIGZ1bmN0aW9uIGlzIG91dCBvZiBTZW1hbnRpYyBWZXJzaW9uaW5nLCBpLmUuIGNhbiBjaGFuZ2UgdW5leHBlY3RlZGx5LiBVc2FnZSBpcyBhdCB5b3VyIG93biByaXNrLlxuICovXG5mdW5jdGlvbiB0cmFuc2Zvcm1Tb3VyY2Uoc291cmNlLCB0cmFuc2Zvcm1WYWx1ZSkge1xuICAgIGNvbnN0IHRyYW5zZm9ybUxvYWRSZXN1bHQgPSAobG9hZFJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAoaXNGaW5hbFJlc3VsdExvYWRlZChsb2FkUmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybVZhbHVlKGxvYWRSZXN1bHQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBnZXRSZXN1bHQgPSBsb2FkUmVzdWx0KCk7XG4gICAgICAgICAgICBpZiAoaXNQcm9taXNlKGdldFJlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0UmVzdWx0LnRoZW4odHJhbnNmb3JtVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybVZhbHVlKGdldFJlc3VsdCk7XG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gKG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgbG9hZFJlc3VsdCA9IHNvdXJjZShvcHRpb25zKTtcbiAgICAgICAgaWYgKGlzUHJvbWlzZShsb2FkUmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGxvYWRSZXN1bHQudGhlbih0cmFuc2Zvcm1Mb2FkUmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJhbnNmb3JtTG9hZFJlc3VsdChsb2FkUmVzdWx0KTtcbiAgICB9O1xufVxuXG4vKlxuICogRnVuY3Rpb25zIHRvIGhlbHAgd2l0aCBmZWF0dXJlcyB0aGF0IHZhcnkgdGhyb3VnaCBicm93c2Vyc1xuICovXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIGJhc2VkIG9uIFRyaWRlbnQgKHRoZSBJbnRlcm5ldCBFeHBsb3JlciBlbmdpbmUpIHdpdGhvdXQgdXNpbmcgdXNlci1hZ2VudC5cbiAqXG4gKiBXYXJuaW5nIGZvciBwYWNrYWdlIHVzZXJzOlxuICogVGhpcyBmdW5jdGlvbiBpcyBvdXQgb2YgU2VtYW50aWMgVmVyc2lvbmluZywgaS5lLiBjYW4gY2hhbmdlIHVuZXhwZWN0ZWRseS4gVXNhZ2UgaXMgYXQgeW91ciBvd24gcmlzay5cbiAqL1xuZnVuY3Rpb24gaXNUcmlkZW50KCkge1xuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgbiA9IG5hdmlnYXRvcjtcbiAgICAvLyBUaGUgcHJvcGVydGllcyBhcmUgY2hlY2tlZCB0byBiZSBpbiBJRSAxMCwgSUUgMTEgYW5kIG5vdCB0byBiZSBpbiBvdGhlciBicm93c2VycyBpbiBPY3RvYmVyIDIwMjBcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgJ01TQ1NTTWF0cml4JyBpbiB3LFxuICAgICAgICAnbXNTZXRJbW1lZGlhdGUnIGluIHcsXG4gICAgICAgICdtc0luZGV4ZWREQicgaW4gdyxcbiAgICAgICAgJ21zTWF4VG91Y2hQb2ludHMnIGluIG4sXG4gICAgICAgICdtc1BvaW50ZXJFbmFibGVkJyBpbiBuLFxuICAgIF0pID49IDQpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBFZGdlSFRNTCAodGhlIHByZS1DaHJvbWl1bSBFZGdlIGVuZ2luZSkgd2l0aG91dCB1c2luZyB1c2VyLWFnZW50LlxuICpcbiAqIFdhcm5pbmcgZm9yIHBhY2thZ2UgdXNlcnM6XG4gKiBUaGlzIGZ1bmN0aW9uIGlzIG91dCBvZiBTZW1hbnRpYyBWZXJzaW9uaW5nLCBpLmUuIGNhbiBjaGFuZ2UgdW5leHBlY3RlZGx5LiBVc2FnZSBpcyBhdCB5b3VyIG93biByaXNrLlxuICovXG5mdW5jdGlvbiBpc0VkZ2VIVE1MKCkge1xuICAgIC8vIEJhc2VkIG9uIHJlc2VhcmNoIGluIE9jdG9iZXIgMjAyMFxuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgbiA9IG5hdmlnYXRvcjtcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFsnbXNXcml0ZVByb2ZpbGVyTWFyaycgaW4gdywgJ01TU3RyZWFtJyBpbiB3LCAnbXNMYXVuY2hVcmknIGluIG4sICdtc1NhdmVCbG9iJyBpbiBuXSkgPj0gMyAmJlxuICAgICAgICAhaXNUcmlkZW50KCkpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBDaHJvbWl1bSB3aXRob3V0IHVzaW5nIHVzZXItYWdlbnQuXG4gKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGlzQ2hyb21pdW0oKSB7XG4gICAgLy8gQmFzZWQgb24gcmVzZWFyY2ggaW4gT2N0b2JlciAyMDIwLiBUZXN0ZWQgdG8gZGV0ZWN0IENocm9taXVtIDQyLTg2LlxuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgbiA9IG5hdmlnYXRvcjtcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgJ3dlYmtpdFBlcnNpc3RlbnRTdG9yYWdlJyBpbiBuLFxuICAgICAgICAnd2Via2l0VGVtcG9yYXJ5U3RvcmFnZScgaW4gbixcbiAgICAgICAgKG4udmVuZG9yIHx8ICcnKS5pbmRleE9mKCdHb29nbGUnKSA9PT0gMCxcbiAgICAgICAgJ3dlYmtpdFJlc29sdmVMb2NhbEZpbGVTeXN0ZW1VUkwnIGluIHcsXG4gICAgICAgICdCYXR0ZXJ5TWFuYWdlcicgaW4gdyxcbiAgICAgICAgJ3dlYmtpdE1lZGlhU3RyZWFtJyBpbiB3LFxuICAgICAgICAnd2Via2l0U3BlZWNoR3JhbW1hcicgaW4gdyxcbiAgICBdKSA+PSA1KTtcbn1cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgdGhlIGJyb3dzZXIgaXMgYmFzZWQgb24gbW9iaWxlIG9yIGRlc2t0b3AgU2FmYXJpIHdpdGhvdXQgdXNpbmcgdXNlci1hZ2VudC5cbiAqIEFsbCBpT1MgYnJvd3NlcnMgdXNlIFdlYktpdCAodGhlIFNhZmFyaSBlbmdpbmUpLlxuICpcbiAqIFdhcm5pbmcgZm9yIHBhY2thZ2UgdXNlcnM6XG4gKiBUaGlzIGZ1bmN0aW9uIGlzIG91dCBvZiBTZW1hbnRpYyBWZXJzaW9uaW5nLCBpLmUuIGNhbiBjaGFuZ2UgdW5leHBlY3RlZGx5LiBVc2FnZSBpcyBhdCB5b3VyIG93biByaXNrLlxuICovXG5mdW5jdGlvbiBpc1dlYktpdCgpIHtcbiAgICAvLyBCYXNlZCBvbiByZXNlYXJjaCBpbiBBdWd1c3QgMjAyNFxuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgbiA9IG5hdmlnYXRvcjtcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgJ0FwcGxlUGF5RXJyb3InIGluIHcsXG4gICAgICAgICdDU1NQcmltaXRpdmVWYWx1ZScgaW4gdyxcbiAgICAgICAgJ0NvdW50ZXInIGluIHcsXG4gICAgICAgIG4udmVuZG9yLmluZGV4T2YoJ0FwcGxlJykgPT09IDAsXG4gICAgICAgICdSR0JDb2xvcicgaW4gdyxcbiAgICAgICAgJ1dlYktpdE1lZGlhS2V5cycgaW4gdyxcbiAgICBdKSA+PSA0KTtcbn1cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgdGhpcyBXZWJLaXQgYnJvd3NlciBpcyBhIGRlc2t0b3AgYnJvd3Nlci5cbiAqIEl0IGRvZXNuJ3QgY2hlY2sgdGhhdCB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBXZWJLaXQsIHRoZXJlIGlzIGEgc2VwYXJhdGUgZnVuY3Rpb24gZm9yIHRoaXMuXG4gKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGlzRGVza3RvcFdlYktpdCgpIHtcbiAgICAvLyBDaGVja2VkIGluIFNhZmFyaSBhbmQgRHVja0R1Y2tHb1xuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgeyBIVE1MRWxlbWVudCwgRG9jdW1lbnQgfSA9IHc7XG4gICAgcmV0dXJuIChjb3VudFRydXRoeShbXG4gICAgICAgICdzYWZhcmknIGluIHcsXG4gICAgICAgICEoJ29uZ2VzdHVyZWVuZCcgaW4gdyksXG4gICAgICAgICEoJ1RvdWNoRXZlbnQnIGluIHcpLFxuICAgICAgICAhKCdvcmllbnRhdGlvbicgaW4gdyksXG4gICAgICAgIEhUTUxFbGVtZW50ICYmICEoJ2F1dG9jYXBpdGFsaXplJyBpbiBIVE1MRWxlbWVudC5wcm90b3R5cGUpLFxuICAgICAgICBEb2N1bWVudCAmJiAncG9pbnRlckxvY2tFbGVtZW50JyBpbiBEb2N1bWVudC5wcm90b3R5cGUsXG4gICAgXSkgPj0gNCk7XG59XG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoaXMgV2ViS2l0IGJyb3dzZXIgaXMgU2FmYXJpLlxuICogSXQgZG9lc24ndCBjaGVjayB0aGF0IHRoZSBicm93c2VyIGlzIGJhc2VkIG9uIFdlYktpdCwgdGhlcmUgaXMgYSBzZXBhcmF0ZSBmdW5jdGlvbiBmb3IgdGhpcy5cbiAqXG4gKiBXYXJuaW5nISBUaGUgZnVuY3Rpb24gd29ya3MgcHJvcGVybHkgb25seSBmb3IgU2FmYXJpIHZlcnNpb24gMTUuNCBhbmQgbmV3ZXIuXG4gKi9cbmZ1bmN0aW9uIGlzU2FmYXJpV2ViS2l0KCkge1xuICAgIC8vIENoZWNrZWQgaW4gU2FmYXJpLCBDaHJvbWUsIEZpcmVmb3gsIFlhbmRleCwgVUMgQnJvd3NlciwgT3BlcmEsIEVkZ2UgYW5kIER1Y2tEdWNrR28uXG4gICAgLy8gaU9TIFNhZmFyaSBhbmQgQ2hyb21lIHdlcmUgY2hlY2tlZCBvbiBpT1MgMTEtMTguIER1Y2tEdWNrR28gd2FzIGNoZWNrZWQgb24gaU9TIDE3LTE4IGFuZCBtYWNPUyAxNC0xNS5cbiAgICAvLyBEZXNrdG9wIFNhZmFyaSB2ZXJzaW9ucyAxMi0xOCB3ZXJlIGNoZWNrZWQuXG4gICAgLy8gVGhlIG90aGVyIGJyb3dzZXJzIHdlcmUgY2hlY2tlZCBvbiBpT1MgMTcgYW5kIDE4OyB0aGVyZSB3YXMgbm8gY2hhbmNlIHRvIGNoZWNrIHRoZW0gb24gdGhlIG90aGVyIE9TIHZlcnNpb25zLlxuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgcmV0dXJuIChcbiAgICAvLyBGaWx0ZXJzLW91dCBDaHJvbWUsIFlhbmRleCwgRHVja0R1Y2tHbyAobWFjT1MgYW5kIGlPUyksIEVkZ2VcbiAgICBpc0Z1bmN0aW9uTmF0aXZlKHcucHJpbnQpICYmXG4gICAgICAgIC8vIERvZXNuJ3Qgd29yayBpbiBTYWZhcmkgPCAxNS40XG4gICAgICAgIFN0cmluZyh3LmJyb3dzZXIpID09PSAnW29iamVjdCBXZWJQYWdlTmFtZXNwYWNlXScpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBHZWNrbyAoRmlyZWZveCBlbmdpbmUpIHdpdGhvdXQgdXNpbmcgdXNlci1hZ2VudC5cbiAqXG4gKiBXYXJuaW5nIGZvciBwYWNrYWdlIHVzZXJzOlxuICogVGhpcyBmdW5jdGlvbiBpcyBvdXQgb2YgU2VtYW50aWMgVmVyc2lvbmluZywgaS5lLiBjYW4gY2hhbmdlIHVuZXhwZWN0ZWRseS4gVXNhZ2UgaXMgYXQgeW91ciBvd24gcmlzay5cbiAqL1xuZnVuY3Rpb24gaXNHZWNrbygpIHtcbiAgICB2YXIgX2EsIF9iO1xuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgLy8gQmFzZWQgb24gcmVzZWFyY2ggaW4gU2VwdGVtYmVyIDIwMjBcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgJ2J1aWxkSUQnIGluIG5hdmlnYXRvcixcbiAgICAgICAgJ01vekFwcGVhcmFuY2UnIGluICgoX2IgPSAoX2EgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zdHlsZSkgIT09IG51bGwgJiYgX2IgIT09IHZvaWQgMCA/IF9iIDoge30pLFxuICAgICAgICAnb25tb3pmdWxsc2NyZWVuY2hhbmdlJyBpbiB3LFxuICAgICAgICAnbW96SW5uZXJTY3JlZW5YJyBpbiB3LFxuICAgICAgICAnQ1NTTW96RG9jdW1lbnRSdWxlJyBpbiB3LFxuICAgICAgICAnQ2FudmFzQ2FwdHVyZU1lZGlhU3RyZWFtJyBpbiB3LFxuICAgIF0pID49IDQpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBDaHJvbWl1bSB2ZXJzaW9uIFx1MjI2NTg2IHdpdGhvdXQgdXNpbmcgdXNlci1hZ2VudC5cbiAqIEl0IGRvZXNuJ3QgY2hlY2sgdGhhdCB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBDaHJvbWl1bSwgdGhlcmUgaXMgYSBzZXBhcmF0ZSBmdW5jdGlvbiBmb3IgdGhpcy5cbiAqL1xuZnVuY3Rpb24gaXNDaHJvbWl1bTg2T3JOZXdlcigpIHtcbiAgICAvLyBDaGVja2VkIGluIENocm9tZSA4NSB2cyBDaHJvbWUgODYgYm90aCBvbiBkZXNrdG9wIGFuZCBBbmRyb2lkLiBDaGVja2VkIGluIG1hY09TIENocm9tZSAxMjgsIEFuZHJvaWQgQ2hyb21lIDEyNy5cbiAgICBjb25zdCB3ID0gd2luZG93O1xuICAgIHJldHVybiAoY291bnRUcnV0aHkoW1xuICAgICAgICAhKCdNZWRpYVNldHRpbmdzUmFuZ2UnIGluIHcpLFxuICAgICAgICAnUlRDRW5jb2RlZEF1ZGlvRnJhbWUnIGluIHcsXG4gICAgICAgICcnICsgdy5JbnRsID09PSAnW29iamVjdCBJbnRsXScsXG4gICAgICAgICcnICsgdy5SZWZsZWN0ID09PSAnW29iamVjdCBSZWZsZWN0XScsXG4gICAgXSkgPj0gMyk7XG59XG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIGJhc2VkIG9uIENocm9taXVtIHZlcnNpb24gXHUyMjY1MTIyIHdpdGhvdXQgdXNpbmcgdXNlci1hZ2VudC5cbiAqIEl0IGRvZXNuJ3QgY2hlY2sgdGhhdCB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBDaHJvbWl1bSwgdGhlcmUgaXMgYSBzZXBhcmF0ZSBmdW5jdGlvbiBmb3IgdGhpcy5cbiAqL1xuZnVuY3Rpb24gaXNDaHJvbWl1bTEyMk9yTmV3ZXIoKSB7XG4gICAgLy8gQ2hlY2tlZCBpbiBDaHJvbWUgMTIxIHZzIENocm9tZSAxMjIgYW5kIDEyOSBib3RoIG9uIGRlc2t0b3AgYW5kIEFuZHJvaWRcbiAgICBjb25zdCB3ID0gd2luZG93O1xuICAgIGNvbnN0IHsgVVJMUGF0dGVybiB9ID0gdztcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgJ3VuaW9uJyBpbiBTZXQucHJvdG90eXBlLFxuICAgICAgICAnSXRlcmF0b3InIGluIHcsXG4gICAgICAgIFVSTFBhdHRlcm4gJiYgJ2hhc1JlZ0V4cEdyb3VwcycgaW4gVVJMUGF0dGVybi5wcm90b3R5cGUsXG4gICAgICAgICdSR0I4JyBpbiBXZWJHTFJlbmRlcmluZ0NvbnRleHQucHJvdG90eXBlLFxuICAgIF0pID49IDMpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBXZWJLaXQgdmVyc2lvbiBcdTIyNjU2MDYgKFNhZmFyaSBcdTIyNjUxMikgd2l0aG91dCB1c2luZyB1c2VyLWFnZW50LlxuICogSXQgZG9lc24ndCBjaGVjayB0aGF0IHRoZSBicm93c2VyIGlzIGJhc2VkIG9uIFdlYktpdCwgdGhlcmUgaXMgYSBzZXBhcmF0ZSBmdW5jdGlvbiBmb3IgdGhpcy5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhZmFyaV92ZXJzaW9uX2hpc3RvcnkjUmVsZWFzZV9oaXN0b3J5IFNhZmFyaS1XZWJLaXQgdmVyc2lvbnMgbWFwXG4gKi9cbmZ1bmN0aW9uIGlzV2ViS2l0NjA2T3JOZXdlcigpIHtcbiAgICAvLyBDaGVja2VkIGluIFNhZmFyaSA5XHUyMDEzMThcbiAgICBjb25zdCB3ID0gd2luZG93O1xuICAgIHJldHVybiAoY291bnRUcnV0aHkoW1xuICAgICAgICAnRE9NUmVjdExpc3QnIGluIHcsXG4gICAgICAgICdSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50JyBpbiB3LFxuICAgICAgICAnU1ZHR2VvbWV0cnlFbGVtZW50JyBpbiB3LFxuICAgICAgICAnb250cmFuc2l0aW9uY2FuY2VsJyBpbiB3LFxuICAgIF0pID49IDMpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgYnJvd3NlciBpcyBiYXNlZCBvbiBXZWJLaXQgdmVyc2lvbiBcdTIyNjU2MTYgKFNhZmFyaSBcdTIyNjUxNykgd2l0aG91dCB1c2luZyB1c2VyLWFnZW50LlxuICogSXQgZG9lc24ndCBjaGVjayB0aGF0IHRoZSBicm93c2VyIGlzIGJhc2VkIG9uIFdlYktpdCwgdGhlcmUgaXMgYSBzZXBhcmF0ZSBmdW5jdGlvbiBmb3IgdGhpcy5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLmFwcGxlLmNvbS9kb2N1bWVudGF0aW9uL3NhZmFyaS1yZWxlYXNlLW5vdGVzL3NhZmFyaS0xNy1yZWxlYXNlLW5vdGVzIFNhZmFyaSAxNyByZWxlYXNlIG5vdGVzXG4gKiBAc2VlIGh0dHBzOi8vdGF1cmkuYXBwL3YxL3JlZmVyZW5jZXMvd2Vidmlldy12ZXJzaW9ucy8jd2Via2l0LXZlcnNpb25zLWluLXNhZmFyaSBTYWZhcmktV2ViS2l0IHZlcnNpb25zIG1hcFxuICovXG5mdW5jdGlvbiBpc1dlYktpdDYxNk9yTmV3ZXIoKSB7XG4gICAgY29uc3QgdyA9IHdpbmRvdztcbiAgICBjb25zdCBuID0gbmF2aWdhdG9yO1xuICAgIGNvbnN0IHsgQ1NTLCBIVE1MQnV0dG9uRWxlbWVudCB9ID0gdztcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgISgnZ2V0U3RvcmFnZVVwZGF0ZXMnIGluIG4pLFxuICAgICAgICBIVE1MQnV0dG9uRWxlbWVudCAmJiAncG9wb3ZlcicgaW4gSFRNTEJ1dHRvbkVsZW1lbnQucHJvdG90eXBlLFxuICAgICAgICAnQ1NTQ291bnRlclN0eWxlUnVsZScgaW4gdyxcbiAgICAgICAgQ1NTLnN1cHBvcnRzKCdmb250LXNpemUtYWRqdXN0OiBleC1oZWlnaHQgMC41JyksXG4gICAgICAgIENTUy5zdXBwb3J0cygndGV4dC10cmFuc2Zvcm06IGZ1bGwtd2lkdGgnKSxcbiAgICBdKSA+PSA0KTtcbn1cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgdGhlIGRldmljZSBpcyBhbiBpUGFkLlxuICogSXQgZG9lc24ndCBjaGVjayB0aGF0IHRoZSBlbmdpbmUgaXMgV2ViS2l0IGFuZCB0aGF0IHRoZSBXZWJLaXQgaXNuJ3QgZGVza3RvcC5cbiAqL1xuZnVuY3Rpb24gaXNJUGFkKCkge1xuICAgIC8vIENoZWNrZWQgb246XG4gICAgLy8gU2FmYXJpIG9uIGlQYWRPUyAoYm90aCBtb2JpbGUgYW5kIGRlc2t0b3AgbW9kZXMpOiA4LCAxMS0xOFxuICAgIC8vIENocm9tZSBvbiBpUGFkT1MgKGJvdGggbW9iaWxlIGFuZCBkZXNrdG9wIG1vZGVzKTogMTEtMThcbiAgICAvLyBTYWZhcmkgb24gaU9TIChib3RoIG1vYmlsZSBhbmQgZGVza3RvcCBtb2Rlcyk6IDktMThcbiAgICAvLyBDaHJvbWUgb24gaU9TIChib3RoIG1vYmlsZSBhbmQgZGVza3RvcCBtb2Rlcyk6IDktMThcbiAgICAvLyBCZWZvcmUgaU9TIDEzLiBTYWZhcmkgdGFtcGVycyB0aGUgdmFsdWUgaW4gXCJyZXF1ZXN0IGRlc2t0b3Agc2l0ZVwiIG1vZGUgc2luY2UgaU9TIDEzLlxuICAgIGlmIChuYXZpZ2F0b3IucGxhdGZvcm0gPT09ICdpUGFkJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgcyA9IHNjcmVlbjtcbiAgICBjb25zdCBzY3JlZW5SYXRpbyA9IHMud2lkdGggLyBzLmhlaWdodDtcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgLy8gU2luY2UgaU9TIDEzLiBEb2Vzbid0IHdvcmsgaW4gQ2hyb21lIG9uIGlQYWRPUyA8MTUsIGJ1dCB3b3JrcyBpbiBkZXNrdG9wIG1vZGUuXG4gICAgICAgICdNZWRpYVNvdXJjZScgaW4gd2luZG93LFxuICAgICAgICAvLyBTaW5jZSBpT1MgMTIuIERvZXNuJ3Qgd29yayBpbiBDaHJvbWUgb24gaVBhZE9TLlxuICAgICAgICAhIUVsZW1lbnQucHJvdG90eXBlLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuLFxuICAgICAgICAvLyBpUGhvbmUgNFMgdGhhdCBydW5zIGlPUyA5IG1hdGNoZXMgdGhpcywgYnV0IGl0IGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgICAgLy8gRG9lc24ndCB3b3JrIGluIGluY29nbml0byBtb2RlIG9mIFNhZmFyaSBcdTIyNjUxNyB3aXRoIHNwbGl0IHNjcmVlbiBiZWNhdXNlIG9mIHRyYWNraW5nIHByZXZlbnRpb25cbiAgICAgICAgc2NyZWVuUmF0aW8gPiAwLjY1ICYmIHNjcmVlblJhdGlvIDwgMS41MyxcbiAgICBdKSA+PSAyKTtcbn1cbi8qKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGdldEZ1bGxzY3JlZW5FbGVtZW50KCkge1xuICAgIGNvbnN0IGQgPSBkb2N1bWVudDtcbiAgICByZXR1cm4gZC5mdWxsc2NyZWVuRWxlbWVudCB8fCBkLm1zRnVsbHNjcmVlbkVsZW1lbnQgfHwgZC5tb3pGdWxsU2NyZWVuRWxlbWVudCB8fCBkLndlYmtpdEZ1bGxzY3JlZW5FbGVtZW50IHx8IG51bGw7XG59XG5mdW5jdGlvbiBleGl0RnVsbHNjcmVlbigpIHtcbiAgICBjb25zdCBkID0gZG9jdW1lbnQ7XG4gICAgLy8gYGNhbGxgIGlzIHJlcXVpcmVkIGJlY2F1c2UgdGhlIGZ1bmN0aW9uIHRocm93cyBhbiBlcnJvciB3aXRob3V0IGEgcHJvcGVyIFwidGhpc1wiIGNvbnRleHRcbiAgICByZXR1cm4gKGQuZXhpdEZ1bGxzY3JlZW4gfHwgZC5tc0V4aXRGdWxsc2NyZWVuIHx8IGQubW96Q2FuY2VsRnVsbFNjcmVlbiB8fCBkLndlYmtpdEV4aXRGdWxsc2NyZWVuKS5jYWxsKGQpO1xufVxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgZGV2aWNlIHJ1bnMgb24gQW5kcm9pZCB3aXRob3V0IHVzaW5nIHVzZXItYWdlbnQuXG4gKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGlzQW5kcm9pZCgpIHtcbiAgICBjb25zdCBpc0l0Q2hyb21pdW0gPSBpc0Nocm9taXVtKCk7XG4gICAgY29uc3QgaXNJdEdlY2tvID0gaXNHZWNrbygpO1xuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgbiA9IG5hdmlnYXRvcjtcbiAgICBjb25zdCBjID0gJ2Nvbm5lY3Rpb24nO1xuICAgIC8vIENocm9tZSByZW1vdmVzIGFsbCB3b3JkcyBcIkFuZHJvaWRcIiBmcm9tIGBuYXZpZ2F0b3JgIHdoZW4gZGVza3RvcCB2ZXJzaW9uIGlzIHJlcXVlc3RlZFxuICAgIC8vIEZpcmVmb3gga2VlcHMgXCJBbmRyb2lkXCIgaW4gYG5hdmlnYXRvci5hcHBWZXJzaW9uYCB3aGVuIGRlc2t0b3AgdmVyc2lvbiBpcyByZXF1ZXN0ZWRcbiAgICBpZiAoaXNJdENocm9taXVtKSB7XG4gICAgICAgIHJldHVybiAoY291bnRUcnV0aHkoW1xuICAgICAgICAgICAgISgnU2hhcmVkV29ya2VyJyBpbiB3KSxcbiAgICAgICAgICAgIC8vIGB0eXBlY2hhbmdlYCBpcyBkZXByZWNhdGVkLCBidXQgaXQncyBzdGlsbCBwcmVzZW50IG9uIEFuZHJvaWQgKHRlc3RlZCBvbiBDaHJvbWUgTW9iaWxlIDExNylcbiAgICAgICAgICAgIC8vIFJlbW92YWwgcHJvcG9zYWwgaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9Njk5ODkyXG4gICAgICAgICAgICAvLyBOb3RlOiB0aGlzIGV4cHJlc3Npb24gcmV0dXJucyB0cnVlIG9uIENocm9tZU9TLCBzbyBhZGRpdGlvbmFsIGRldGVjdG9ycyBhcmUgcmVxdWlyZWQgdG8gYXZvaWQgZmFsc2UtcG9zaXRpdmVzXG4gICAgICAgICAgICBuW2NdICYmICdvbnR5cGVjaGFuZ2UnIGluIG5bY10sXG4gICAgICAgICAgICAhKCdzaW5rSWQnIGluIG5ldyBBdWRpbygpKSxcbiAgICAgICAgXSkgPj0gMik7XG4gICAgfVxuICAgIGVsc2UgaWYgKGlzSXRHZWNrbykge1xuICAgICAgICByZXR1cm4gY291bnRUcnV0aHkoWydvbm9yaWVudGF0aW9uY2hhbmdlJyBpbiB3LCAnb3JpZW50YXRpb24nIGluIHcsIC9hbmRyb2lkL2kudGVzdChuLmFwcFZlcnNpb24pXSkgPj0gMjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIE9ubHkgMiBicm93c2VyIGVuZ2luZXMgYXJlIHByZXNlbnRlZCBvbiBBbmRyb2lkLlxuICAgICAgICAvLyBBY3R1YWxseSwgdGhlcmUgaXMgYWxzbyBBbmRyb2lkIDQuMSBicm93c2VyLCBidXQgaXQncyBub3Qgd29ydGggZGV0ZWN0aW5nIGl0IGF0IHRoZSBtb21lbnQuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIFNhbXN1bmcgSW50ZXJuZXQgd2l0aG91dCB1c2luZyB1c2VyLWFnZW50LlxuICogSXQgZG9lc24ndCBjaGVjayB0aGF0IHRoZSBicm93c2VyIGlzIGJhc2VkIG9uIENocm9taXVtLCBwbGVhc2UgdXNlIGBpc0Nocm9taXVtYCBiZWZvcmUgdXNpbmcgdGhpcyBmdW5jdGlvbi5cbiAqXG4gKiBXYXJuaW5nIGZvciBwYWNrYWdlIHVzZXJzOlxuICogVGhpcyBmdW5jdGlvbiBpcyBvdXQgb2YgU2VtYW50aWMgVmVyc2lvbmluZywgaS5lLiBjYW4gY2hhbmdlIHVuZXhwZWN0ZWRseS4gVXNhZ2UgaXMgYXQgeW91ciBvd24gcmlzay5cbiAqL1xuZnVuY3Rpb24gaXNTYW1zdW5nSW50ZXJuZXQoKSB7XG4gICAgLy8gQ2hlY2tlZCBpbiBTYW1zdW5nIEludGVybmV0IDIxLCAyNSBhbmQgMjdcbiAgICBjb25zdCBuID0gbmF2aWdhdG9yO1xuICAgIGNvbnN0IHcgPSB3aW5kb3c7XG4gICAgY29uc3QgYXVkaW9Qcm90b3R5cGUgPSBBdWRpby5wcm90b3R5cGU7XG4gICAgY29uc3QgeyB2aXN1YWxWaWV3cG9ydCB9ID0gdztcbiAgICByZXR1cm4gKGNvdW50VHJ1dGh5KFtcbiAgICAgICAgJ3NyTGF0ZW5jeScgaW4gYXVkaW9Qcm90b3R5cGUsXG4gICAgICAgICdzckNoYW5uZWxDb3VudCcgaW4gYXVkaW9Qcm90b3R5cGUsXG4gICAgICAgICdkZXZpY2VQb3N0dXJlJyBpbiBuLFxuICAgICAgICB2aXN1YWxWaWV3cG9ydCAmJiAnc2VnbWVudHMnIGluIHZpc3VhbFZpZXdwb3J0LFxuICAgICAgICAnZ2V0VGV4dEluZm9ybWF0aW9uJyBpbiBJbWFnZS5wcm90b3R5cGUsIC8vIE5vdCBhdmFpbGFibGUgaW4gU2Ftc3VuZyBJbnRlcm5ldCAyMVxuICAgIF0pID49IDMpO1xufVxuXG4vKipcbiAqIEEgZGVlcCBkZXNjcmlwdGlvbjogaHR0cHM6Ly9maW5nZXJwcmludC5jb20vYmxvZy9hdWRpby1maW5nZXJwcmludGluZy9cbiAqIEluc3BpcmVkIGJ5IGFuZCBiYXNlZCBvbiBodHRwczovL2dpdGh1Yi5jb20vY296eWxpZmUvYXVkaW8tZmluZ2VycHJpbnRcbiAqXG4gKiBBIHZlcnNpb24gb2YgdGhlIGVudHJvcHkgc291cmNlIHdpdGggc3RhYmlsaXphdGlvbiB0byBtYWtlIGl0IHN1aXRhYmxlIGZvciBzdGF0aWMgZmluZ2VycHJpbnRpbmcuXG4gKiBBdWRpbyBzaWduYWwgaXMgbm9pc2VkIGluIHByaXZhdGUgbW9kZSBvZiBTYWZhcmkgMTcsIHNvIGF1ZGlvIGZpbmdlcnByaW50aW5nIGlzIHNraXBwZWQgaW4gU2FmYXJpIDE3LlxuICovXG5mdW5jdGlvbiBnZXRBdWRpb0ZpbmdlcnByaW50KCkge1xuICAgIGlmIChkb2VzQnJvd3NlclBlcmZvcm1BbnRpZmluZ2VycHJpbnRpbmckMSgpKSB7XG4gICAgICAgIHJldHVybiAtNCAvKiBTcGVjaWFsRmluZ2VycHJpbnQuS25vd25Gb3JBbnRpZmluZ2VycHJpbnRpbmcgKi87XG4gICAgfVxuICAgIHJldHVybiBnZXRVbnN0YWJsZUF1ZGlvRmluZ2VycHJpbnQoKTtcbn1cbi8qKlxuICogQSB2ZXJzaW9uIG9mIHRoZSBlbnRyb3B5IHNvdXJjZSB3aXRob3V0IHN0YWJpbGl6YXRpb24uXG4gKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGdldFVuc3RhYmxlQXVkaW9GaW5nZXJwcmludCgpIHtcbiAgICBjb25zdCB3ID0gd2luZG93O1xuICAgIGNvbnN0IEF1ZGlvQ29udGV4dCA9IHcuT2ZmbGluZUF1ZGlvQ29udGV4dCB8fCB3LndlYmtpdE9mZmxpbmVBdWRpb0NvbnRleHQ7XG4gICAgaWYgKCFBdWRpb0NvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIC0yIC8qIFNwZWNpYWxGaW5nZXJwcmludC5Ob3RTdXBwb3J0ZWQgKi87XG4gICAgfVxuICAgIC8vIEluIHNvbWUgYnJvd3NlcnMsIGF1ZGlvIGNvbnRleHQgYWx3YXlzIHN0YXlzIHN1c3BlbmRlZCB1bmxlc3MgdGhlIGNvbnRleHQgaXMgc3RhcnRlZCBpbiByZXNwb25zZSB0byBhIHVzZXIgYWN0aW9uXG4gICAgLy8gKGUuZy4gYSBjbGljayBvciBhIHRhcCkuIEl0IHByZXZlbnRzIGF1ZGlvIGZpbmdlcnByaW50IGZyb20gYmVpbmcgdGFrZW4gYXQgYW4gYXJiaXRyYXJ5IG1vbWVudCBvZiB0aW1lLlxuICAgIC8vIFN1Y2ggYnJvd3NlcnMgYXJlIG9sZCBhbmQgdW5wb3B1bGFyLCBzbyB0aGUgYXVkaW8gZmluZ2VycHJpbnRpbmcgaXMganVzdCBza2lwcGVkIGluIHRoZW0uXG4gICAgLy8gU2VlIGEgc2ltaWxhciBjYXNlIGV4cGxhbmF0aW9uIGF0IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ2MzYzMDQ4L29uYXVkaW9wcm9jZXNzLW5vdC1jYWxsZWQtb24taW9zMTEjNDY1MzQwODhcbiAgICBpZiAoZG9lc0Jyb3dzZXJTdXNwZW5kQXVkaW9Db250ZXh0KCkpIHtcbiAgICAgICAgcmV0dXJuIC0xIC8qIFNwZWNpYWxGaW5nZXJwcmludC5Lbm93bkZvclN1c3BlbmRpbmcgKi87XG4gICAgfVxuICAgIGNvbnN0IGhhc2hGcm9tSW5kZXggPSA0NTAwO1xuICAgIGNvbnN0IGhhc2hUb0luZGV4ID0gNTAwMDtcbiAgICBjb25zdCBjb250ZXh0ID0gbmV3IEF1ZGlvQ29udGV4dCgxLCBoYXNoVG9JbmRleCwgNDQxMDApO1xuICAgIGNvbnN0IG9zY2lsbGF0b3IgPSBjb250ZXh0LmNyZWF0ZU9zY2lsbGF0b3IoKTtcbiAgICBvc2NpbGxhdG9yLnR5cGUgPSAndHJpYW5nbGUnO1xuICAgIG9zY2lsbGF0b3IuZnJlcXVlbmN5LnZhbHVlID0gMTAwMDA7XG4gICAgY29uc3QgY29tcHJlc3NvciA9IGNvbnRleHQuY3JlYXRlRHluYW1pY3NDb21wcmVzc29yKCk7XG4gICAgY29tcHJlc3Nvci50aHJlc2hvbGQudmFsdWUgPSAtNTA7XG4gICAgY29tcHJlc3Nvci5rbmVlLnZhbHVlID0gNDA7XG4gICAgY29tcHJlc3Nvci5yYXRpby52YWx1ZSA9IDEyO1xuICAgIGNvbXByZXNzb3IuYXR0YWNrLnZhbHVlID0gMDtcbiAgICBjb21wcmVzc29yLnJlbGVhc2UudmFsdWUgPSAwLjI1O1xuICAgIG9zY2lsbGF0b3IuY29ubmVjdChjb21wcmVzc29yKTtcbiAgICBjb21wcmVzc29yLmNvbm5lY3QoY29udGV4dC5kZXN0aW5hdGlvbik7XG4gICAgb3NjaWxsYXRvci5zdGFydCgwKTtcbiAgICBjb25zdCBbcmVuZGVyUHJvbWlzZSwgZmluaXNoUmVuZGVyaW5nXSA9IHN0YXJ0UmVuZGVyaW5nQXVkaW8oY29udGV4dCk7XG4gICAgLy8gU3VwcHJlc3NlcyB0aGUgY29uc29sZSBlcnJvciBtZXNzYWdlIGluIGNhc2Ugd2hlbiB0aGUgZmluZ2VycHJpbnQgZmFpbHMgYmVmb3JlIHJlcXVlc3RlZFxuICAgIGNvbnN0IGZpbmdlcnByaW50UHJvbWlzZSA9IHN1cHByZXNzVW5oYW5kbGVkUmVqZWN0aW9uV2FybmluZyhyZW5kZXJQcm9taXNlLnRoZW4oKGJ1ZmZlcikgPT4gZ2V0SGFzaChidWZmZXIuZ2V0Q2hhbm5lbERhdGEoMCkuc3ViYXJyYXkoaGFzaEZyb21JbmRleCkpLCAoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yLm5hbWUgPT09IFwidGltZW91dFwiIC8qIElubmVyRXJyb3JOYW1lLlRpbWVvdXQgKi8gfHwgZXJyb3IubmFtZSA9PT0gXCJzdXNwZW5kZWRcIiAvKiBJbm5lckVycm9yTmFtZS5TdXNwZW5kZWQgKi8pIHtcbiAgICAgICAgICAgIHJldHVybiAtMyAvKiBTcGVjaWFsRmluZ2VycHJpbnQuVGltZW91dCAqLztcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KSk7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgZmluaXNoUmVuZGVyaW5nKCk7XG4gICAgICAgIHJldHVybiBmaW5nZXJwcmludFByb21pc2U7XG4gICAgfTtcbn1cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGJyb3dzZXIgaXMga25vd24gZm9yIGFsd2F5cyBzdXNwZW5kaW5nIGF1ZGlvIGNvbnRleHRcbiAqL1xuZnVuY3Rpb24gZG9lc0Jyb3dzZXJTdXNwZW5kQXVkaW9Db250ZXh0KCkge1xuICAgIC8vIE1vYmlsZSBTYWZhcmkgMTEgYW5kIG9sZGVyXG4gICAgcmV0dXJuIGlzV2ViS2l0KCkgJiYgIWlzRGVza3RvcFdlYktpdCgpICYmICFpc1dlYktpdDYwNk9yTmV3ZXIoKTtcbn1cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGJyb3dzZXIgaXMga25vd24gZm9yIGFwcGx5aW5nIGFudGktZmluZ2VycHJpbnRpbmcgbWVhc3VyZXMgaW4gYWxsIG9yIHNvbWUgY3JpdGljYWwgbW9kZXNcbiAqL1xuZnVuY3Rpb24gZG9lc0Jyb3dzZXJQZXJmb3JtQW50aWZpbmdlcnByaW50aW5nJDEoKSB7XG4gICAgcmV0dXJuIChcbiAgICAvLyBTYWZhcmkgXHUyMjY1MTdcbiAgICAoaXNXZWJLaXQoKSAmJiBpc1dlYktpdDYxNk9yTmV3ZXIoKSAmJiBpc1NhZmFyaVdlYktpdCgpKSB8fFxuICAgICAgICAvLyBTYW1zdW5nIEludGVybmV0IFx1MjI2NTI2XG4gICAgICAgIChpc0Nocm9taXVtKCkgJiYgaXNTYW1zdW5nSW50ZXJuZXQoKSAmJiBpc0Nocm9taXVtMTIyT3JOZXdlcigpKSk7XG59XG4vKipcbiAqIFN0YXJ0cyByZW5kZXJpbmcgdGhlIGF1ZGlvIGNvbnRleHQuXG4gKiBXaGVuIHRoZSByZXR1cm5lZCBmdW5jdGlvbiBpcyBjYWxsZWQsIHRoZSByZW5kZXIgcHJvY2VzcyBzdGFydHMgZmluaXNoaW5nLlxuICovXG5mdW5jdGlvbiBzdGFydFJlbmRlcmluZ0F1ZGlvKGNvbnRleHQpIHtcbiAgICBjb25zdCByZW5kZXJUcnlNYXhDb3VudCA9IDM7XG4gICAgY29uc3QgcmVuZGVyUmV0cnlEZWxheSA9IDUwMDtcbiAgICBjb25zdCBydW5uaW5nTWF4QXdhaXRUaW1lID0gNTAwO1xuICAgIGNvbnN0IHJ1bm5pbmdTdWZmaWNpZW50VGltZSA9IDUwMDA7XG4gICAgbGV0IGZpbmFsaXplID0gKCkgPT4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHJlc3VsdFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGxldCBpc0ZpbmFsaXplZCA9IGZhbHNlO1xuICAgICAgICBsZXQgcmVuZGVyVHJ5Q291bnQgPSAwO1xuICAgICAgICBsZXQgc3RhcnRlZFJ1bm5pbmdBdCA9IDA7XG4gICAgICAgIGNvbnRleHQub25jb21wbGV0ZSA9IChldmVudCkgPT4gcmVzb2x2ZShldmVudC5yZW5kZXJlZEJ1ZmZlcik7XG4gICAgICAgIGNvbnN0IHN0YXJ0UnVubmluZ1RpbWVvdXQgPSAoKSA9PiB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHJlamVjdChtYWtlSW5uZXJFcnJvcihcInRpbWVvdXRcIiAvKiBJbm5lckVycm9yTmFtZS5UaW1lb3V0ICovKSksIE1hdGgubWluKHJ1bm5pbmdNYXhBd2FpdFRpbWUsIHN0YXJ0ZWRSdW5uaW5nQXQgKyBydW5uaW5nU3VmZmljaWVudFRpbWUgLSBEYXRlLm5vdygpKSk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHRyeVJlbmRlciA9ICgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVuZGVyaW5nUHJvbWlzZSA9IGNvbnRleHQuc3RhcnRSZW5kZXJpbmcoKTtcbiAgICAgICAgICAgICAgICAvLyBgY29udGV4dC5zdGFydFJlbmRlcmluZ2AgaGFzIHR3byBBUElzOiBQcm9taXNlIGFuZCBjYWxsYmFjaywgd2UgY2hlY2sgdGhhdCBpdCdzIHJlYWxseSBhIHByb21pc2UganVzdCBpbiBjYXNlXG4gICAgICAgICAgICAgICAgaWYgKGlzUHJvbWlzZShyZW5kZXJpbmdQcm9taXNlKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTdXBwcmVzc2VzIGFsbCB1bmhhbmRsZWQgcmVqZWN0aW9ucyBpbiBjYXNlIG9mIHNjaGVkdWxlZCByZWR1bmRhbnQgcmV0cmllcyBhZnRlciBzdWNjZXNzZnVsIHJlbmRlcmluZ1xuICAgICAgICAgICAgICAgICAgICBzdXBwcmVzc1VuaGFuZGxlZFJlamVjdGlvbldhcm5pbmcocmVuZGVyaW5nUHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN3aXRjaCAoY29udGV4dC5zdGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdydW5uaW5nJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ZWRSdW5uaW5nQXQgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmluYWxpemVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRSdW5uaW5nVGltZW91dCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNvbWV0aW1lcyB0aGUgYXVkaW8gY29udGV4dCBkb2Vzbid0IHN0YXJ0IGFmdGVyIGNhbGxpbmcgYHN0YXJ0UmVuZGVyaW5nYCAoaW4gYWRkaXRpb24gdG8gdGhlIGNhc2VzIHdoZXJlXG4gICAgICAgICAgICAgICAgICAgIC8vIGF1ZGlvIGNvbnRleHQgZG9lc24ndCBzdGFydCBhdCBhbGwpLiBBIGtub3duIGNhc2UgaXMgc3RhcnRpbmcgYW4gYXVkaW8gY29udGV4dCB3aGVuIHRoZSBicm93c2VyIHRhYiBpcyBpblxuICAgICAgICAgICAgICAgICAgICAvLyBiYWNrZ3JvdW5kIG9uIGlQaG9uZS4gUmV0cmllcyB1c3VhbGx5IGhlbHAgaW4gdGhpcyBjYXNlLlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdzdXNwZW5kZWQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGF1ZGlvIGNvbnRleHQgY2FuIHJlamVjdCBzdGFydGluZyB1bnRpbCB0aGUgdGFiIGlzIGluIGZvcmVncm91bmQuIExvbmcgZmluZ2VycHJpbnQgZHVyYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIGJhY2tncm91bmQgaXNuJ3QgYSBwcm9ibGVtLCB0aGVyZWZvcmUgdGhlIHJldHJ5IGF0dGVtcHRzIGRvbid0IGNvdW50IGluIGJhY2tncm91bmQuIEl0IGNhbiBsZWFkIHRvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIHNpdHVhdGlvbiB3aGVuIGEgZmluZ2VycHJpbnQgdGFrZXMgdmVyeSBsb25nIHRpbWUgYW5kIGZpbmlzaGVzIHN1Y2Nlc3NmdWxseS4gRllJLCB0aGUgYXVkaW8gY29udGV4dFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FuIGJlIHN1c3BlbmRlZCB3aGVuIGBkb2N1bWVudC5oaWRkZW4gPT09IGZhbHNlYCBhbmQgc3RhcnQgcnVubmluZyBhZnRlciBhIHJldHJ5LlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2N1bWVudC5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJUcnlDb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmluYWxpemVkICYmIHJlbmRlclRyeUNvdW50ID49IHJlbmRlclRyeU1heENvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG1ha2VJbm5lckVycm9yKFwic3VzcGVuZGVkXCIgLyogSW5uZXJFcnJvck5hbWUuU3VzcGVuZGVkICovKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KHRyeVJlbmRlciwgcmVuZGVyUmV0cnlEZWxheSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0cnlSZW5kZXIoKTtcbiAgICAgICAgZmluYWxpemUgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWlzRmluYWxpemVkKSB7XG4gICAgICAgICAgICAgICAgaXNGaW5hbGl6ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGlmIChzdGFydGVkUnVubmluZ0F0ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBzdGFydFJ1bm5pbmdUaW1lb3V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH0pO1xuICAgIHJldHVybiBbcmVzdWx0UHJvbWlzZSwgZmluYWxpemVdO1xufVxuZnVuY3Rpb24gZ2V0SGFzaChzaWduYWwpIHtcbiAgICBsZXQgaGFzaCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaWduYWwubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaGFzaCArPSBNYXRoLmFicyhzaWduYWxbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gaGFzaDtcbn1cbmZ1bmN0aW9uIG1ha2VJbm5lckVycm9yKG5hbWUpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihuYW1lKTtcbiAgICBlcnJvci5uYW1lID0gbmFtZTtcbiAgICByZXR1cm4gZXJyb3I7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbmQga2VlcHMgYW4gaW52aXNpYmxlIGlmcmFtZSB3aGlsZSB0aGUgZ2l2ZW4gZnVuY3Rpb24gcnVucy5cbiAqIFRoZSBnaXZlbiBmdW5jdGlvbiBpcyBjYWxsZWQgd2hlbiB0aGUgaWZyYW1lIGlzIGxvYWRlZCBhbmQgaGFzIGEgYm9keS5cbiAqIFRoZSBpZnJhbWUgYWxsb3dzIHRvIG1lYXN1cmUgRE9NIHNpemVzIGluc2lkZSBpdHNlbGYuXG4gKlxuICogTm90aWNlOiBwYXNzaW5nIGFuIGluaXRpYWwgSFRNTCBjb2RlIGRvZXNuJ3Qgd29yayBpbiBJRS5cbiAqXG4gKiBXYXJuaW5nIGZvciBwYWNrYWdlIHVzZXJzOlxuICogVGhpcyBmdW5jdGlvbiBpcyBvdXQgb2YgU2VtYW50aWMgVmVyc2lvbmluZywgaS5lLiBjYW4gY2hhbmdlIHVuZXhwZWN0ZWRseS4gVXNhZ2UgaXMgYXQgeW91ciBvd24gcmlzay5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gd2l0aElmcmFtZShhY3Rpb24sIGluaXRpYWxIdG1sLCBkb21Qb2xsSW50ZXJ2YWwgPSA1MCkge1xuICAgIHZhciBfYSwgX2IsIF9jO1xuICAgIGNvbnN0IGQgPSBkb2N1bWVudDtcbiAgICAvLyBkb2N1bWVudC5ib2R5IGNhbiBiZSBudWxsIHdoaWxlIHRoZSBwYWdlIGlzIGxvYWRpbmdcbiAgICB3aGlsZSAoIWQuYm9keSkge1xuICAgICAgICBhd2FpdCB3YWl0KGRvbVBvbGxJbnRlcnZhbCk7XG4gICAgfVxuICAgIGNvbnN0IGlmcmFtZSA9IGQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKF9yZXNvbHZlLCBfcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsZXQgaXNDb21wbGV0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29uc3QgcmVzb2x2ZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBpc0NvbXBsZXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBfcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlamVjdCA9IChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlzQ29tcGxldGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIF9yZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmcmFtZS5vbmxvYWQgPSByZXNvbHZlO1xuICAgICAgICAgICAgaWZyYW1lLm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICAgICAgICBjb25zdCB7IHN0eWxlIH0gPSBpZnJhbWU7XG4gICAgICAgICAgICBzdHlsZS5zZXRQcm9wZXJ0eSgnZGlzcGxheScsICdibG9jaycsICdpbXBvcnRhbnQnKTsgLy8gUmVxdWlyZWQgZm9yIGJyb3dzZXJzIHRvIGNhbGN1bGF0ZSB0aGUgbGF5b3V0XG4gICAgICAgICAgICBzdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgICAgICBzdHlsZS50b3AgPSAnMCc7XG4gICAgICAgICAgICBzdHlsZS5sZWZ0ID0gJzAnO1xuICAgICAgICAgICAgc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuICAgICAgICAgICAgaWYgKGluaXRpYWxIdG1sICYmICdzcmNkb2MnIGluIGlmcmFtZSkge1xuICAgICAgICAgICAgICAgIGlmcmFtZS5zcmNkb2MgPSBpbml0aWFsSHRtbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmcmFtZS5zcmMgPSAnYWJvdXQ6YmxhbmsnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZC5ib2R5LmFwcGVuZENoaWxkKGlmcmFtZSk7XG4gICAgICAgICAgICAvLyBXZWJLaXQgaW4gV2VDaGF0IGRvZXNuJ3QgZmlyZSB0aGUgaWZyYW1lJ3MgYG9ubG9hZGAgZm9yIHNvbWUgcmVhc29uLlxuICAgICAgICAgICAgLy8gVGhpcyBjb2RlIGNoZWNrcyBmb3IgdGhlIGxvYWRpbmcgc3RhdGUgbWFudWFsbHkuXG4gICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9pc3N1ZXMvNjQ1XG4gICAgICAgICAgICBjb25zdCBjaGVja1JlYWR5U3RhdGUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgICAgICAgICAvLyBUaGUgcmVhZHkgc3RhdGUgbWF5IG5ldmVyIGJlY29tZSAnY29tcGxldGUnIGluIEZpcmVmb3ggZGVzcGl0ZSB0aGUgJ2xvYWQnIGV2ZW50IGJlaW5nIGZpcmVkLlxuICAgICAgICAgICAgICAgIC8vIFNvIGFuIGluZmluaXRlIHNldFRpbWVvdXQgbG9vcCBjYW4gaGFwcGVuIHdpdGhvdXQgdGhpcyBjaGVjay5cbiAgICAgICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9wdWxsLzcxNiNpc3N1ZWNvbW1lbnQtOTg2ODk4Nzk2XG4gICAgICAgICAgICAgICAgaWYgKGlzQ29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBNYWtlIHN1cmUgaWZyYW1lLmNvbnRlbnRXaW5kb3cgYW5kIGlmcmFtZS5jb250ZW50V2luZG93LmRvY3VtZW50IGFyZSBib3RoIGxvYWRlZFxuICAgICAgICAgICAgICAgIC8vIFRoZSBjb250ZW50V2luZG93LmRvY3VtZW50IGNhbiBtaXNzIGluIEpTRE9NIChodHRwczovL2dpdGh1Yi5jb20vanNkb20vanNkb20pLlxuICAgICAgICAgICAgICAgIGlmICgoKF9iID0gKF9hID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5kb2N1bWVudCkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnJlYWR5U3RhdGUpID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoY2hlY2tSZWFkeVN0YXRlLCAxMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNoZWNrUmVhZHlTdGF0ZSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgd2hpbGUgKCEoKF9iID0gKF9hID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5kb2N1bWVudCkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmJvZHkpKSB7XG4gICAgICAgICAgICBhd2FpdCB3YWl0KGRvbVBvbGxJbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IGFjdGlvbihpZnJhbWUsIGlmcmFtZS5jb250ZW50V2luZG93KTtcbiAgICB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIChfYyA9IGlmcmFtZS5wYXJlbnROb2RlKSA9PT0gbnVsbCB8fCBfYyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2MucmVtb3ZlQ2hpbGQoaWZyYW1lKTtcbiAgICB9XG59XG4vKipcbiAqIENyZWF0ZXMgYSBET00gZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIGdpdmVuIHNlbGVjdG9yLlxuICogT25seSBzaW5nbGUgZWxlbWVudCBzZWxlY3RvciBhcmUgc3VwcG9ydGVkICh3aXRob3V0IG9wZXJhdG9ycyBsaWtlIHNwYWNlLCArLCA+LCBldGMpLlxuICovXG5mdW5jdGlvbiBzZWxlY3RvclRvRWxlbWVudChzZWxlY3Rvcikge1xuICAgIGNvbnN0IFt0YWcsIGF0dHJpYnV0ZXNdID0gcGFyc2VTaW1wbGVDc3NTZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnICE9PSBudWxsICYmIHRhZyAhPT0gdm9pZCAwID8gdGFnIDogJ2RpdicpO1xuICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzKSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGF0dHJpYnV0ZXNbbmFtZV0uam9pbignICcpO1xuICAgICAgICAvLyBDaGFuZ2luZyB0aGUgYHN0eWxlYCBhdHRyaWJ1dGUgY2FuIGNhdXNlIGEgQ1NQIGVycm9yLCB0aGVyZWZvcmUgd2UgY2hhbmdlIHRoZSBgc3R5bGUuY3NzVGV4dGAgcHJvcGVydHkuXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9maW5nZXJwcmludGpzL2ZpbmdlcnByaW50anMvaXNzdWVzLzczM1xuICAgICAgICBpZiAobmFtZSA9PT0gJ3N0eWxlJykge1xuICAgICAgICAgICAgYWRkU3R5bGVTdHJpbmcoZWxlbWVudC5zdHlsZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBlbGVtZW50O1xufVxuLyoqXG4gKiBBZGRzIENTUyBzdHlsZXMgZnJvbSBhIHN0cmluZyBpbiBzdWNoIGEgd2F5IHRoYXQgZG9lc24ndCB0cmlnZ2VyIGEgQ1NQIHdhcm5pbmcgKHVuc2FmZS1pbmxpbmUgb3IgdW5zYWZlLWV2YWwpXG4gKi9cbmZ1bmN0aW9uIGFkZFN0eWxlU3RyaW5nKHN0eWxlLCBzb3VyY2UpIHtcbiAgICAvLyBXZSBkb24ndCB1c2UgYHN0eWxlLmNzc1RleHRgIGJlY2F1c2UgYnJvd3NlcnMgbXVzdCBibG9jayBpdCB3aGVuIG5vIGB1bnNhZmUtZXZhbGAgQ1NQIGlzIHByZXNlbnRlZDogaHR0cHM6Ly9jc3BsaXRlLmNvbS9jc3AxNDUvI3czY19ub3RlXG4gICAgLy8gRXZlbiB0aG91Z2ggdGhlIGJyb3dzZXJzIGlnbm9yZSB0aGlzIHN0YW5kYXJkLCB3ZSBkb24ndCB1c2UgYGNzc1RleHRgIGp1c3QgaW4gY2FzZS5cbiAgICBmb3IgKGNvbnN0IHByb3BlcnR5IG9mIHNvdXJjZS5zcGxpdCgnOycpKSB7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gL15cXHMqKFtcXHctXSspXFxzKjpcXHMqKC4rPykoXFxzKiEoW1xcdy1dKykpP1xccyokLy5leGVjKHByb3BlcnR5KTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBjb25zdCBbLCBuYW1lLCB2YWx1ZSwgLCBwcmlvcml0eV0gPSBtYXRjaDtcbiAgICAgICAgICAgIHN0eWxlLnNldFByb3BlcnR5KG5hbWUsIHZhbHVlLCBwcmlvcml0eSB8fCAnJyk7IC8vIFRoZSBsYXN0IGFyZ3VtZW50IGNhbid0IGJlIHVuZGVmaW5lZCBpbiBJRTExXG4gICAgICAgIH1cbiAgICB9XG59XG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgY29kZSBydW5zIGluIGFuIGlmcmFtZSwgYW5kIGFueSBwYXJlbnQgcGFnZSdzIG9yaWdpbiBkb2Vzbid0IG1hdGNoIHRoZSBjdXJyZW50IG9yaWdpblxuICovXG5mdW5jdGlvbiBpc0FueVBhcmVudENyb3NzT3JpZ2luKCkge1xuICAgIGxldCBjdXJyZW50V2luZG93ID0gd2luZG93O1xuICAgIGZvciAoOzspIHtcbiAgICAgICAgY29uc3QgcGFyZW50V2luZG93ID0gY3VycmVudFdpbmRvdy5wYXJlbnQ7XG4gICAgICAgIGlmICghcGFyZW50V2luZG93IHx8IHBhcmVudFdpbmRvdyA9PT0gY3VycmVudFdpbmRvdykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBUaGUgdG9wIHBhZ2UgaXMgcmVhY2hlZFxuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAocGFyZW50V2luZG93LmxvY2F0aW9uLm9yaWdpbiAhPT0gY3VycmVudFdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIFRoZSBlcnJvciBpcyB0aHJvd24gd2hlbiBgb3JpZ2luYCBpcyBhY2Nlc3NlZCBvbiBgcGFyZW50V2luZG93LmxvY2F0aW9uYCB3aGVuIHRoZSBwYXJlbnQgaXMgY3Jvc3Mtb3JpZ2luXG4gICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5uYW1lID09PSAnU2VjdXJpdHlFcnJvcicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRXaW5kb3cgPSBwYXJlbnRXaW5kb3c7XG4gICAgfVxufVxuXG4vLyBXZSB1c2UgbSBvciB3IGJlY2F1c2UgdGhlc2UgdHdvIGNoYXJhY3RlcnMgdGFrZSB1cCB0aGUgbWF4aW11bSB3aWR0aC5cbi8vIEFuZCB3ZSB1c2UgYSBMTGkgc28gdGhhdCB0aGUgc2FtZSBtYXRjaGluZyBmb250cyBjYW4gZ2V0IHNlcGFyYXRlZC5cbmNvbnN0IHRlc3RTdHJpbmcgPSAnbW1Nd1dMbGlJME8mMSc7XG4vLyBXZSB0ZXN0IHVzaW5nIDQ4cHggZm9udCBzaXplLCB3ZSBtYXkgdXNlIGFueSBzaXplLiBJIGd1ZXNzIGxhcmdlciB0aGUgYmV0dGVyLlxuY29uc3QgdGV4dFNpemUgPSAnNDhweCc7XG4vLyBBIGZvbnQgd2lsbCBiZSBjb21wYXJlZCBhZ2FpbnN0IGFsbCB0aGUgdGhyZWUgZGVmYXVsdCBmb250cy5cbi8vIEFuZCBpZiBmb3IgYW55IGRlZmF1bHQgZm9udHMgaXQgZG9lc24ndCBtYXRjaCwgdGhlbiB0aGF0IGZvbnQgaXMgYXZhaWxhYmxlLlxuY29uc3QgYmFzZUZvbnRzID0gWydtb25vc3BhY2UnLCAnc2Fucy1zZXJpZicsICdzZXJpZiddO1xuY29uc3QgZm9udExpc3QgPSBbXG4gICAgLy8gVGhpcyBpcyBhbmRyb2lkLXNwZWNpZmljIGZvbnQgZnJvbSBcIlJvYm90b1wiIGZhbWlseVxuICAgICdzYW5zLXNlcmlmLXRoaW4nLFxuICAgICdBUk5PIFBSTycsXG4gICAgJ0FnZW5jeSBGQicsXG4gICAgJ0FyYWJpYyBUeXBlc2V0dGluZycsXG4gICAgJ0FyaWFsIFVuaWNvZGUgTVMnLFxuICAgICdBdmFudEdhcmRlIEJrIEJUJyxcbiAgICAnQmFua0dvdGhpYyBNZCBCVCcsXG4gICAgJ0JhdGFuZycsXG4gICAgJ0JpdHN0cmVhbSBWZXJhIFNhbnMgTW9ubycsXG4gICAgJ0NhbGlicmknLFxuICAgICdDZW50dXJ5JyxcbiAgICAnQ2VudHVyeSBHb3RoaWMnLFxuICAgICdDbGFyZW5kb24nLFxuICAgICdFVVJPU1RJTEUnLFxuICAgICdGcmFua2xpbiBHb3RoaWMnLFxuICAgICdGdXR1cmEgQmsgQlQnLFxuICAgICdGdXR1cmEgTWQgQlQnLFxuICAgICdHT1RIQU0nLFxuICAgICdHaWxsIFNhbnMnLFxuICAgICdIRUxWJyxcbiAgICAnSGFldHRlbnNjaHdlaWxlcicsXG4gICAgJ0hlbHZldGljYSBOZXVlJyxcbiAgICAnSHVtYW5zdDUyMSBCVCcsXG4gICAgJ0xlZWxhd2FkZWUnLFxuICAgICdMZXR0ZXIgR290aGljJyxcbiAgICAnTGV2ZW5pbSBNVCcsXG4gICAgJ0x1Y2lkYSBCcmlnaHQnLFxuICAgICdMdWNpZGEgU2FucycsXG4gICAgJ01lbmxvJyxcbiAgICAnTVMgTWluY2hvJyxcbiAgICAnTVMgT3V0bG9vaycsXG4gICAgJ01TIFJlZmVyZW5jZSBTcGVjaWFsdHknLFxuICAgICdNUyBVSSBHb3RoaWMnLFxuICAgICdNVCBFeHRyYScsXG4gICAgJ01ZUklBRCBQUk8nLFxuICAgICdNYXJsZXR0JyxcbiAgICAnTWVpcnlvIFVJJyxcbiAgICAnTWljcm9zb2Z0IFVpZ2h1cicsXG4gICAgJ01pbmlvbiBQcm8nLFxuICAgICdNb25vdHlwZSBDb3JzaXZhJyxcbiAgICAnUE1pbmdMaVUnLFxuICAgICdQcmlzdGluYScsXG4gICAgJ1NDUklQVElOQScsXG4gICAgJ1NlZ29lIFVJIExpZ2h0JyxcbiAgICAnU2VyaWZhJyxcbiAgICAnU2ltSGVpJyxcbiAgICAnU21hbGwgRm9udHMnLFxuICAgICdTdGFjY2F0bzIyMiBCVCcsXG4gICAgJ1RSQUpBTiBQUk8nLFxuICAgICdVbml2ZXJzIENFIDU1IE1lZGl1bScsXG4gICAgJ1ZyaW5kYScsXG4gICAgJ1pXQWRvYmVGJyxcbl07XG4vLyBrdWRvcyB0byBodHRwOi8vd3d3LmxhbGl0Lm9yZy9sYWIvamF2YXNjcmlwdC1jc3MtZm9udC1kZXRlY3QvXG5mdW5jdGlvbiBnZXRGb250cygpIHtcbiAgICAvLyBSdW5uaW5nIHRoZSBzY3JpcHQgaW4gYW4gaWZyYW1lIG1ha2VzIGl0IG5vdCBhZmZlY3QgdGhlIHBhZ2UgbG9vayBhbmQgbm90IGJlIGFmZmVjdGVkIGJ5IHRoZSBwYWdlIENTUy4gU2VlOlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9maW5nZXJwcmludGpzL2ZpbmdlcnByaW50anMvaXNzdWVzLzU5MlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9maW5nZXJwcmludGpzL2ZpbmdlcnByaW50anMvaXNzdWVzLzYyOFxuICAgIHJldHVybiB3aXRoSWZyYW1lKGFzeW5jIChfLCB7IGRvY3VtZW50IH0pID0+IHtcbiAgICAgICAgY29uc3QgaG9sZGVyID0gZG9jdW1lbnQuYm9keTtcbiAgICAgICAgaG9sZGVyLnN0eWxlLmZvbnRTaXplID0gdGV4dFNpemU7XG4gICAgICAgIC8vIGRpdiB0byBsb2FkIHNwYW5zIGZvciB0aGUgZGVmYXVsdCBmb250cyBhbmQgdGhlIGZvbnRzIHRvIGRldGVjdFxuICAgICAgICBjb25zdCBzcGFuc0NvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBzcGFuc0NvbnRhaW5lci5zdHlsZS5zZXRQcm9wZXJ0eSgndmlzaWJpbGl0eScsICdoaWRkZW4nLCAnaW1wb3J0YW50Jyk7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRXaWR0aCA9IHt9O1xuICAgICAgICBjb25zdCBkZWZhdWx0SGVpZ2h0ID0ge307XG4gICAgICAgIC8vIGNyZWF0ZXMgYSBzcGFuIHdoZXJlIHRoZSBmb250cyB3aWxsIGJlIGxvYWRlZFxuICAgICAgICBjb25zdCBjcmVhdGVTcGFuID0gKGZvbnRGYW1pbHkpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICAgICAgICBjb25zdCB7IHN0eWxlIH0gPSBzcGFuO1xuICAgICAgICAgICAgc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICAgICAgc3R5bGUudG9wID0gJzAnO1xuICAgICAgICAgICAgc3R5bGUubGVmdCA9ICcwJztcbiAgICAgICAgICAgIHN0eWxlLmZvbnRGYW1pbHkgPSBmb250RmFtaWx5O1xuICAgICAgICAgICAgc3Bhbi50ZXh0Q29udGVudCA9IHRlc3RTdHJpbmc7XG4gICAgICAgICAgICBzcGFuc0NvbnRhaW5lci5hcHBlbmRDaGlsZChzcGFuKTtcbiAgICAgICAgICAgIHJldHVybiBzcGFuO1xuICAgICAgICB9O1xuICAgICAgICAvLyBjcmVhdGVzIGEgc3BhbiBhbmQgbG9hZCB0aGUgZm9udCB0byBkZXRlY3QgYW5kIGEgYmFzZSBmb250IGZvciBmYWxsYmFja1xuICAgICAgICBjb25zdCBjcmVhdGVTcGFuV2l0aEZvbnRzID0gKGZvbnRUb0RldGVjdCwgYmFzZUZvbnQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVTcGFuKGAnJHtmb250VG9EZXRlY3R9Jywke2Jhc2VGb250fWApO1xuICAgICAgICB9O1xuICAgICAgICAvLyBjcmVhdGVzIHNwYW5zIGZvciB0aGUgYmFzZSBmb250cyBhbmQgYWRkcyB0aGVtIHRvIGJhc2VGb250c0RpdlxuICAgICAgICBjb25zdCBpbml0aWFsaXplQmFzZUZvbnRzU3BhbnMgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYmFzZUZvbnRzLm1hcChjcmVhdGVTcGFuKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gY3JlYXRlcyBzcGFucyBmb3IgdGhlIGZvbnRzIHRvIGRldGVjdCBhbmQgYWRkcyB0aGVtIHRvIGZvbnRzRGl2XG4gICAgICAgIGNvbnN0IGluaXRpYWxpemVGb250c1NwYW5zID0gKCkgPT4ge1xuICAgICAgICAgICAgLy8gU3RvcmVzIHtmb250TmFtZSA6IFtzcGFucyBmb3IgdGhhdCBmb250XX1cbiAgICAgICAgICAgIGNvbnN0IHNwYW5zID0ge307XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZvbnQgb2YgZm9udExpc3QpIHtcbiAgICAgICAgICAgICAgICBzcGFuc1tmb250XSA9IGJhc2VGb250cy5tYXAoKGJhc2VGb250KSA9PiBjcmVhdGVTcGFuV2l0aEZvbnRzKGZvbnQsIGJhc2VGb250KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3BhbnM7XG4gICAgICAgIH07XG4gICAgICAgIC8vIGNoZWNrcyBpZiBhIGZvbnQgaXMgYXZhaWxhYmxlXG4gICAgICAgIGNvbnN0IGlzRm9udEF2YWlsYWJsZSA9IChmb250U3BhbnMpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBiYXNlRm9udHMuc29tZSgoYmFzZUZvbnQsIGJhc2VGb250SW5kZXgpID0+IGZvbnRTcGFuc1tiYXNlRm9udEluZGV4XS5vZmZzZXRXaWR0aCAhPT0gZGVmYXVsdFdpZHRoW2Jhc2VGb250XSB8fFxuICAgICAgICAgICAgICAgIGZvbnRTcGFuc1tiYXNlRm9udEluZGV4XS5vZmZzZXRIZWlnaHQgIT09IGRlZmF1bHRIZWlnaHRbYmFzZUZvbnRdKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gY3JlYXRlIHNwYW5zIGZvciBiYXNlIGZvbnRzXG4gICAgICAgIGNvbnN0IGJhc2VGb250c1NwYW5zID0gaW5pdGlhbGl6ZUJhc2VGb250c1NwYW5zKCk7XG4gICAgICAgIC8vIGNyZWF0ZSBzcGFucyBmb3IgZm9udHMgdG8gZGV0ZWN0XG4gICAgICAgIGNvbnN0IGZvbnRzU3BhbnMgPSBpbml0aWFsaXplRm9udHNTcGFucygpO1xuICAgICAgICAvLyBhZGQgYWxsIHRoZSBzcGFucyB0byB0aGUgRE9NXG4gICAgICAgIGhvbGRlci5hcHBlbmRDaGlsZChzcGFuc0NvbnRhaW5lcik7XG4gICAgICAgIC8vIGdldCB0aGUgZGVmYXVsdCB3aWR0aCBmb3IgdGhlIHRocmVlIGJhc2UgZm9udHNcbiAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGJhc2VGb250cy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgIGRlZmF1bHRXaWR0aFtiYXNlRm9udHNbaW5kZXhdXSA9IGJhc2VGb250c1NwYW5zW2luZGV4XS5vZmZzZXRXaWR0aDsgLy8gd2lkdGggZm9yIHRoZSBkZWZhdWx0IGZvbnRcbiAgICAgICAgICAgIGRlZmF1bHRIZWlnaHRbYmFzZUZvbnRzW2luZGV4XV0gPSBiYXNlRm9udHNTcGFuc1tpbmRleF0ub2Zmc2V0SGVpZ2h0OyAvLyBoZWlnaHQgZm9yIHRoZSBkZWZhdWx0IGZvbnRcbiAgICAgICAgfVxuICAgICAgICAvLyBjaGVjayBhdmFpbGFibGUgZm9udHNcbiAgICAgICAgcmV0dXJuIGZvbnRMaXN0LmZpbHRlcigoZm9udCkgPT4gaXNGb250QXZhaWxhYmxlKGZvbnRzU3BhbnNbZm9udF0pKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0UGx1Z2lucygpIHtcbiAgICBjb25zdCByYXdQbHVnaW5zID0gbmF2aWdhdG9yLnBsdWdpbnM7XG4gICAgaWYgKCFyYXdQbHVnaW5zKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IHBsdWdpbnMgPSBbXTtcbiAgICAvLyBTYWZhcmkgMTAgZG9lc24ndCBzdXBwb3J0IGl0ZXJhdGluZyBuYXZpZ2F0b3IucGx1Z2lucyB3aXRoIGZvci4uLm9mXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYXdQbHVnaW5zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvbnN0IHBsdWdpbiA9IHJhd1BsdWdpbnNbaV07XG4gICAgICAgIGlmICghcGx1Z2luKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtaW1lVHlwZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBwbHVnaW4ubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICAgIGNvbnN0IG1pbWVUeXBlID0gcGx1Z2luW2pdO1xuICAgICAgICAgICAgbWltZVR5cGVzLnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6IG1pbWVUeXBlLnR5cGUsXG4gICAgICAgICAgICAgICAgc3VmZml4ZXM6IG1pbWVUeXBlLnN1ZmZpeGVzLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcGx1Z2lucy5wdXNoKHtcbiAgICAgICAgICAgIG5hbWU6IHBsdWdpbi5uYW1lLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHBsdWdpbi5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIG1pbWVUeXBlcyxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBwbHVnaW5zO1xufVxuXG4vKipcbiAqIEBzZWUgaHR0cHM6Ly93d3cuYnJvd3NlcmxlYWtzLmNvbS9jYW52YXMjaG93LWRvZXMtaXQtd29ya1xuICpcbiAqIEEgdmVyc2lvbiBvZiB0aGUgZW50cm9weSBzb3VyY2Ugd2l0aCBzdGFiaWxpemF0aW9uIHRvIG1ha2UgaXQgc3VpdGFibGUgZm9yIHN0YXRpYyBmaW5nZXJwcmludGluZy5cbiAqIENhbnZhcyBpbWFnZSBpcyBub2lzZWQgaW4gcHJpdmF0ZSBtb2RlIG9mIFNhZmFyaSAxNywgc28gaW1hZ2UgcmVuZGVyaW5nIGlzIHNraXBwZWQgaW4gU2FmYXJpIDE3LlxuICovXG5mdW5jdGlvbiBnZXRDYW52YXNGaW5nZXJwcmludCgpIHtcbiAgICByZXR1cm4gZ2V0VW5zdGFibGVDYW52YXNGaW5nZXJwcmludChkb2VzQnJvd3NlclBlcmZvcm1BbnRpZmluZ2VycHJpbnRpbmcoKSk7XG59XG4vKipcbiAqIEEgdmVyc2lvbiBvZiB0aGUgZW50cm9weSBzb3VyY2Ugd2l0aG91dCBzdGFiaWxpemF0aW9uLlxuICpcbiAqIFdhcm5pbmcgZm9yIHBhY2thZ2UgdXNlcnM6XG4gKiBUaGlzIGZ1bmN0aW9uIGlzIG91dCBvZiBTZW1hbnRpYyBWZXJzaW9uaW5nLCBpLmUuIGNhbiBjaGFuZ2UgdW5leHBlY3RlZGx5LiBVc2FnZSBpcyBhdCB5b3VyIG93biByaXNrLlxuICovXG5mdW5jdGlvbiBnZXRVbnN0YWJsZUNhbnZhc0ZpbmdlcnByaW50KHNraXBJbWFnZXMpIHtcbiAgICBsZXQgd2luZGluZyA9IGZhbHNlO1xuICAgIGxldCBnZW9tZXRyeTtcbiAgICBsZXQgdGV4dDtcbiAgICBjb25zdCBbY2FudmFzLCBjb250ZXh0XSA9IG1ha2VDYW52YXNDb250ZXh0KCk7XG4gICAgaWYgKCFpc1N1cHBvcnRlZChjYW52YXMsIGNvbnRleHQpKSB7XG4gICAgICAgIGdlb21ldHJ5ID0gdGV4dCA9IFwidW5zdXBwb3J0ZWRcIiAvKiBJbWFnZVN0YXR1cy5VbnN1cHBvcnRlZCAqLztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHdpbmRpbmcgPSBkb2VzU3VwcG9ydFdpbmRpbmcoY29udGV4dCk7XG4gICAgICAgIGlmIChza2lwSW1hZ2VzKSB7XG4gICAgICAgICAgICBnZW9tZXRyeSA9IHRleHQgPSBcInNraXBwZWRcIiAvKiBJbWFnZVN0YXR1cy5Ta2lwcGVkICovO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgW2dlb21ldHJ5LCB0ZXh0XSA9IHJlbmRlckltYWdlcyhjYW52YXMsIGNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHdpbmRpbmcsIGdlb21ldHJ5LCB0ZXh0IH07XG59XG5mdW5jdGlvbiBtYWtlQ2FudmFzQ29udGV4dCgpIHtcbiAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICBjYW52YXMud2lkdGggPSAxO1xuICAgIGNhbnZhcy5oZWlnaHQgPSAxO1xuICAgIHJldHVybiBbY2FudmFzLCBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKV07XG59XG5mdW5jdGlvbiBpc1N1cHBvcnRlZChjYW52YXMsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gISEoY29udGV4dCAmJiBjYW52YXMudG9EYXRhVVJMKTtcbn1cbmZ1bmN0aW9uIGRvZXNTdXBwb3J0V2luZGluZyhjb250ZXh0KSB7XG4gICAgLy8gaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTcwODI1MDI0NjU1L2h0dHA6Ly9ibG9ncy5hZG9iZS5jb20vd2VicGxhdGZvcm0vMjAxMy8wMS8zMC93aW5kaW5nLXJ1bGVzLWluLWNhbnZhcy9cbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vTW9kZXJuaXpyL01vZGVybml6ci9ibG9iL21hc3Rlci9mZWF0dXJlLWRldGVjdHMvY2FudmFzL3dpbmRpbmcuanNcbiAgICBjb250ZXh0LnJlY3QoMCwgMCwgMTAsIDEwKTtcbiAgICBjb250ZXh0LnJlY3QoMiwgMiwgNiwgNik7XG4gICAgcmV0dXJuICFjb250ZXh0LmlzUG9pbnRJblBhdGgoNSwgNSwgJ2V2ZW5vZGQnKTtcbn1cbmZ1bmN0aW9uIHJlbmRlckltYWdlcyhjYW52YXMsIGNvbnRleHQpIHtcbiAgICByZW5kZXJUZXh0SW1hZ2UoY2FudmFzLCBjb250ZXh0KTtcbiAgICBjb25zdCB0ZXh0SW1hZ2UxID0gY2FudmFzVG9TdHJpbmcoY2FudmFzKTtcbiAgICBjb25zdCB0ZXh0SW1hZ2UyID0gY2FudmFzVG9TdHJpbmcoY2FudmFzKTsgLy8gSXQncyBzbGlnaHRseSBmYXN0ZXIgdG8gZG91YmxlLWVuY29kZSB0aGUgdGV4dCBpbWFnZVxuICAgIC8vIFNvbWUgYnJvd3NlcnMgYWRkIGEgbm9pc2UgdG8gdGhlIGNhbnZhczogaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9pc3N1ZXMvNzkxXG4gICAgLy8gVGhlIGNhbnZhcyBpcyBleGNsdWRlZCBmcm9tIHRoZSBmaW5nZXJwcmludCBpbiB0aGlzIGNhc2VcbiAgICBpZiAodGV4dEltYWdlMSAhPT0gdGV4dEltYWdlMikge1xuICAgICAgICByZXR1cm4gW1widW5zdGFibGVcIiAvKiBJbWFnZVN0YXR1cy5VbnN0YWJsZSAqLywgXCJ1bnN0YWJsZVwiIC8qIEltYWdlU3RhdHVzLlVuc3RhYmxlICovXTtcbiAgICB9XG4gICAgLy8gVGV4dCBpcyB1bnN0YWJsZTpcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2lzc3Vlcy81ODNcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2lzc3Vlcy8xMDNcbiAgICAvLyBUaGVyZWZvcmUgaXQncyBleHRyYWN0ZWQgaW50byBhIHNlcGFyYXRlIGltYWdlLlxuICAgIHJlbmRlckdlb21ldHJ5SW1hZ2UoY2FudmFzLCBjb250ZXh0KTtcbiAgICBjb25zdCBnZW9tZXRyeUltYWdlID0gY2FudmFzVG9TdHJpbmcoY2FudmFzKTtcbiAgICByZXR1cm4gW2dlb21ldHJ5SW1hZ2UsIHRleHRJbWFnZTFdO1xufVxuZnVuY3Rpb24gcmVuZGVyVGV4dEltYWdlKGNhbnZhcywgY29udGV4dCkge1xuICAgIC8vIFJlc2l6aW5nIHRoZSBjYW52YXMgY2xlYW5zIGl0XG4gICAgY2FudmFzLndpZHRoID0gMjQwO1xuICAgIGNhbnZhcy5oZWlnaHQgPSA2MDtcbiAgICBjb250ZXh0LnRleHRCYXNlbGluZSA9ICdhbHBoYWJldGljJztcbiAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICcjZjYwJztcbiAgICBjb250ZXh0LmZpbGxSZWN0KDEwMCwgMSwgNjIsIDIwKTtcbiAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICcjMDY5JztcbiAgICAvLyBJdCdzIGltcG9ydGFudCB0byB1c2UgZXhwbGljaXQgYnVpbHQtaW4gZm9udHMgaW4gb3JkZXIgdG8gZXhjbHVkZSB0aGUgYWZmZWN0IG9mIGZvbnQgcHJlZmVyZW5jZXNcbiAgICAvLyAodGhlcmUgaXMgYSBzZXBhcmF0ZSBlbnRyb3B5IHNvdXJjZSBmb3IgdGhlbSkuXG4gICAgY29udGV4dC5mb250ID0gJzExcHQgXCJUaW1lcyBOZXcgUm9tYW5cIic7XG4gICAgLy8gVGhlIGNob2ljZSBvZiBlbW9qaXMgaGFzIGEgZ2lnYW50aWMgaW1wYWN0IG9uIHJlbmRlcmluZyBwZXJmb3JtYW5jZSAoZXNwZWNpYWxseSBpbiBGRikuXG4gICAgLy8gU29tZSBuZXdlciBlbW9qaXMgY2F1c2UgaXQgdG8gc2xvdyBkb3duIDUwLTIwMCB0aW1lcy5cbiAgICAvLyBUaGVyZSBtdXN0IGJlIG5vIHRleHQgdG8gdGhlIHJpZ2h0IG9mIHRoZSBlbW9qaSwgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9maW5nZXJwcmludGpzL2ZpbmdlcnByaW50anMvaXNzdWVzLzU3NFxuICAgIC8vIEEgYmFyZSBlbW9qaSBzaG91bGRuJ3QgYmUgdXNlZCBiZWNhdXNlIHRoZSBjYW52YXMgd2lsbCBjaGFuZ2UgZGVwZW5kaW5nIG9uIHRoZSBzY3JpcHQgZW5jb2Rpbmc6XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9pc3N1ZXMvNjZcbiAgICAvLyBFc2NhcGUgc2VxdWVuY2Ugc2hvdWxkbid0IGJlIHVzZWQgdG9vIGJlY2F1c2UgVGVyc2VyIHdpbGwgdHVybiBpdCBpbnRvIGEgYmFyZSB1bmljb2RlLlxuICAgIGNvbnN0IHByaW50ZWRUZXh0ID0gYEN3bSBmam9yZGJhbmsgZ2x5ICR7U3RyaW5nLmZyb21DaGFyQ29kZSg1NTM1NywgNTY4MzUpIC8qIFx1RDgzRFx1REUwMyAqL31gO1xuICAgIGNvbnRleHQuZmlsbFRleHQocHJpbnRlZFRleHQsIDIsIDE1KTtcbiAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICdyZ2JhKDEwMiwgMjA0LCAwLCAwLjIpJztcbiAgICBjb250ZXh0LmZvbnQgPSAnMThwdCBBcmlhbCc7XG4gICAgY29udGV4dC5maWxsVGV4dChwcmludGVkVGV4dCwgNCwgNDUpO1xufVxuZnVuY3Rpb24gcmVuZGVyR2VvbWV0cnlJbWFnZShjYW52YXMsIGNvbnRleHQpIHtcbiAgICAvLyBSZXNpemluZyB0aGUgY2FudmFzIGNsZWFucyBpdFxuICAgIGNhbnZhcy53aWR0aCA9IDEyMjtcbiAgICBjYW52YXMuaGVpZ2h0ID0gMTEwO1xuICAgIC8vIENhbnZhcyBibGVuZGluZ1xuICAgIC8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDE3MDgyNjE5NDEyMS9odHRwOi8vYmxvZ3MuYWRvYmUuY29tL3dlYnBsYXRmb3JtLzIwMTMvMDEvMjgvYmxlbmRpbmctZmVhdHVyZXMtaW4tY2FudmFzL1xuICAgIC8vIGh0dHA6Ly9qc2ZpZGRsZS5uZXQvTkRZVjgvMTYvXG4gICAgY29udGV4dC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSAnbXVsdGlwbHknO1xuICAgIGZvciAoY29uc3QgW2NvbG9yLCB4LCB5XSBvZiBbXG4gICAgICAgIFsnI2YyZicsIDQwLCA0MF0sXG4gICAgICAgIFsnIzJmZicsIDgwLCA0MF0sXG4gICAgICAgIFsnI2ZmMicsIDYwLCA4MF0sXG4gICAgXSkge1xuICAgICAgICBjb250ZXh0LmZpbGxTdHlsZSA9IGNvbG9yO1xuICAgICAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgICAgICBjb250ZXh0LmFyYyh4LCB5LCA0MCwgMCwgTWF0aC5QSSAqIDIsIHRydWUpO1xuICAgICAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgICAgICBjb250ZXh0LmZpbGwoKTtcbiAgICB9XG4gICAgLy8gQ2FudmFzIHdpbmRpbmdcbiAgICAvLyBodHRwczovL3dlYi5hcmNoaXZlLm9yZy93ZWIvMjAxMzA5MTMwNjE2MzIvaHR0cDovL2Jsb2dzLmFkb2JlLmNvbS93ZWJwbGF0Zm9ybS8yMDEzLzAxLzMwL3dpbmRpbmctcnVsZXMtaW4tY2FudmFzL1xuICAgIC8vIGh0dHA6Ly9qc2ZpZGRsZS5uZXQvTkRZVjgvMTkvXG4gICAgY29udGV4dC5maWxsU3R5bGUgPSAnI2Y5Yyc7XG4gICAgY29udGV4dC5hcmMoNjAsIDYwLCA2MCwgMCwgTWF0aC5QSSAqIDIsIHRydWUpO1xuICAgIGNvbnRleHQuYXJjKDYwLCA2MCwgMjAsIDAsIE1hdGguUEkgKiAyLCB0cnVlKTtcbiAgICBjb250ZXh0LmZpbGwoJ2V2ZW5vZGQnKTtcbn1cbmZ1bmN0aW9uIGNhbnZhc1RvU3RyaW5nKGNhbnZhcykge1xuICAgIHJldHVybiBjYW52YXMudG9EYXRhVVJMKCk7XG59XG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBicm93c2VyIGlzIGtub3duIGZvciBhcHBseWluZyBhbnRpLWZpbmdlcnByaW50aW5nIG1lYXN1cmVzIGluIGFsbCBvciBzb21lIGNyaXRpY2FsIG1vZGVzXG4gKi9cbmZ1bmN0aW9uIGRvZXNCcm93c2VyUGVyZm9ybUFudGlmaW5nZXJwcmludGluZygpIHtcbiAgICAvLyBTYWZhcmkgMTdcbiAgICByZXR1cm4gaXNXZWJLaXQoKSAmJiBpc1dlYktpdDYxNk9yTmV3ZXIoKSAmJiBpc1NhZmFyaVdlYktpdCgpO1xufVxuXG4vKipcbiAqIFRoaXMgaXMgYSBjcnVkZSBhbmQgcHJpbWl0aXZlIHRvdWNoIHNjcmVlbiBkZXRlY3Rpb24uIEl0J3Mgbm90IHBvc3NpYmxlIHRvIGN1cnJlbnRseSByZWxpYWJseSBkZXRlY3QgdGhlIGF2YWlsYWJpbGl0eVxuICogb2YgYSB0b3VjaCBzY3JlZW4gd2l0aCBhIEpTLCB3aXRob3V0IGFjdHVhbGx5IHN1YnNjcmliaW5nIHRvIGEgdG91Y2ggZXZlbnQuXG4gKlxuICogQHNlZSBodHRwOi8vd3d3LnN0dWNveC5jb20vYmxvZy95b3UtY2FudC1kZXRlY3QtYS10b3VjaHNjcmVlbi9cbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL01vZGVybml6ci9Nb2Rlcm5penIvaXNzdWVzLzU0OFxuICovXG5mdW5jdGlvbiBnZXRUb3VjaFN1cHBvcnQoKSB7XG4gICAgY29uc3QgbiA9IG5hdmlnYXRvcjtcbiAgICBsZXQgbWF4VG91Y2hQb2ludHMgPSAwO1xuICAgIGxldCB0b3VjaEV2ZW50O1xuICAgIGlmIChuLm1heFRvdWNoUG9pbnRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbWF4VG91Y2hQb2ludHMgPSB0b0ludChuLm1heFRvdWNoUG9pbnRzKTtcbiAgICB9XG4gICAgZWxzZSBpZiAobi5tc01heFRvdWNoUG9pbnRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbWF4VG91Y2hQb2ludHMgPSBuLm1zTWF4VG91Y2hQb2ludHM7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdUb3VjaEV2ZW50Jyk7XG4gICAgICAgIHRvdWNoRXZlbnQgPSB0cnVlO1xuICAgIH1cbiAgICBjYXRjaCAoX2EpIHtcbiAgICAgICAgdG91Y2hFdmVudCA9IGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0b3VjaFN0YXJ0ID0gJ29udG91Y2hzdGFydCcgaW4gd2luZG93O1xuICAgIHJldHVybiB7XG4gICAgICAgIG1heFRvdWNoUG9pbnRzLFxuICAgICAgICB0b3VjaEV2ZW50LFxuICAgICAgICB0b3VjaFN0YXJ0LFxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldE9zQ3B1KCkge1xuICAgIHJldHVybiBuYXZpZ2F0b3Iub3NjcHU7XG59XG5cbmZ1bmN0aW9uIGdldExhbmd1YWdlcygpIHtcbiAgICBjb25zdCBuID0gbmF2aWdhdG9yO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IGxhbmd1YWdlID0gbi5sYW5ndWFnZSB8fCBuLnVzZXJMYW5ndWFnZSB8fCBuLmJyb3dzZXJMYW5ndWFnZSB8fCBuLnN5c3RlbUxhbmd1YWdlO1xuICAgIGlmIChsYW5ndWFnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKFtsYW5ndWFnZV0pO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheShuLmxhbmd1YWdlcykpIHtcbiAgICAgICAgLy8gU3RhcnRpbmcgZnJvbSBDaHJvbWl1bSA4NiwgdGhlcmUgaXMgb25seSBhIHNpbmdsZSB2YWx1ZSBpbiBgbmF2aWdhdG9yLmxhbmd1YWdlYCBpbiBJbmNvZ25pdG8gbW9kZTpcbiAgICAgICAgLy8gdGhlIHZhbHVlIG9mIGBuYXZpZ2F0b3IubGFuZ3VhZ2VgLiBUaGVyZWZvcmUgdGhlIHZhbHVlIGlzIGlnbm9yZWQgaW4gdGhpcyBicm93c2VyLlxuICAgICAgICBpZiAoIShpc0Nocm9taXVtKCkgJiYgaXNDaHJvbWl1bTg2T3JOZXdlcigpKSkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gobi5sYW5ndWFnZXMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiBuLmxhbmd1YWdlcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc3QgbGFuZ3VhZ2VzID0gbi5sYW5ndWFnZXM7XG4gICAgICAgIGlmIChsYW5ndWFnZXMpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGxhbmd1YWdlcy5zcGxpdCgnLCcpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBnZXRDb2xvckRlcHRoKCkge1xuICAgIHJldHVybiB3aW5kb3cuc2NyZWVuLmNvbG9yRGVwdGg7XG59XG5cbmZ1bmN0aW9uIGdldERldmljZU1lbW9yeSgpIHtcbiAgICAvLyBgbmF2aWdhdG9yLmRldmljZU1lbW9yeWAgaXMgYSBzdHJpbmcgY29udGFpbmluZyBhIG51bWJlciBpbiBzb21lIHVuaWRlbnRpZmllZCBjYXNlc1xuICAgIHJldHVybiByZXBsYWNlTmFOKHRvRmxvYXQobmF2aWdhdG9yLmRldmljZU1lbW9yeSksIHVuZGVmaW5lZCk7XG59XG5cbi8qKlxuICogQSB2ZXJzaW9uIG9mIHRoZSBlbnRyb3B5IHNvdXJjZSB3aXRoIHN0YWJpbGl6YXRpb24gdG8gbWFrZSBpdCBzdWl0YWJsZSBmb3Igc3RhdGljIGZpbmdlcnByaW50aW5nLlxuICogVGhlIHdpbmRvdyByZXNvbHV0aW9uIGlzIGFsd2F5cyB0aGUgZG9jdW1lbnQgc2l6ZSBpbiBwcml2YXRlIG1vZGUgb2YgU2FmYXJpIDE3LFxuICogc28gdGhlIHdpbmRvdyByZXNvbHV0aW9uIGlzIG5vdCB1c2VkIGluIFNhZmFyaSAxNy5cbiAqL1xuZnVuY3Rpb24gZ2V0U2NyZWVuUmVzb2x1dGlvbigpIHtcbiAgICBpZiAoaXNXZWJLaXQoKSAmJiBpc1dlYktpdDYxNk9yTmV3ZXIoKSAmJiBpc1NhZmFyaVdlYktpdCgpKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiBnZXRVbnN0YWJsZVNjcmVlblJlc29sdXRpb24oKTtcbn1cbi8qKlxuICogQSB2ZXJzaW9uIG9mIHRoZSBlbnRyb3B5IHNvdXJjZSB3aXRob3V0IHN0YWJpbGl6YXRpb24uXG4gKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGdldFVuc3RhYmxlU2NyZWVuUmVzb2x1dGlvbigpIHtcbiAgICBjb25zdCBzID0gc2NyZWVuO1xuICAgIC8vIFNvbWUgYnJvd3NlcnMgcmV0dXJuIHNjcmVlbiByZXNvbHV0aW9uIGFzIHN0cmluZ3MsIGUuZy4gXCIxMjAwXCIsIGluc3RlYWQgb2YgYSBudW1iZXIsIGUuZy4gMTIwMC5cbiAgICAvLyBJIHN1c3BlY3QgaXQncyBkb25lIGJ5IGNlcnRhaW4gcGx1Z2lucyB0aGF0IHJhbmRvbWl6ZSBicm93c2VyIHByb3BlcnRpZXMgdG8gcHJldmVudCBmaW5nZXJwcmludGluZy5cbiAgICAvLyBTb21lIGJyb3dzZXJzIGV2ZW4gcmV0dXJuICBzY3JlZW4gcmVzb2x1dGlvbiBhcyBub3QgbnVtYmVycy5cbiAgICBjb25zdCBwYXJzZURpbWVuc2lvbiA9ICh2YWx1ZSkgPT4gcmVwbGFjZU5hTih0b0ludCh2YWx1ZSksIG51bGwpO1xuICAgIGNvbnN0IGRpbWVuc2lvbnMgPSBbcGFyc2VEaW1lbnNpb24ocy53aWR0aCksIHBhcnNlRGltZW5zaW9uKHMuaGVpZ2h0KV07XG4gICAgZGltZW5zaW9ucy5zb3J0KCkucmV2ZXJzZSgpO1xuICAgIHJldHVybiBkaW1lbnNpb25zO1xufVxuXG5jb25zdCBzY3JlZW5GcmFtZUNoZWNrSW50ZXJ2YWwgPSAyNTAwO1xuY29uc3Qgcm91bmRpbmdQcmVjaXNpb24gPSAxMDtcbi8vIFRoZSB0eXBlIGlzIHJlYWRvbmx5IHRvIHByb3RlY3QgZnJvbSB1bndhbnRlZCBtdXRhdGlvbnNcbmxldCBzY3JlZW5GcmFtZUJhY2t1cDtcbmxldCBzY3JlZW5GcmFtZVNpemVUaW1lb3V0SWQ7XG4vKipcbiAqIFN0YXJ0cyB3YXRjaGluZyB0aGUgc2NyZWVuIGZyYW1lIHNpemUuIFdoZW4gYSBub24temVybyBzaXplIGFwcGVhcnMsIHRoZSBzaXplIGlzIHNhdmVkIGFuZCB0aGUgd2F0Y2ggaXMgc3RvcHBlZC5cbiAqIExhdGVyLCB3aGVuIGBnZXRTY3JlZW5GcmFtZWAgcnVucywgaXQgd2lsbCByZXR1cm4gdGhlIHNhdmVkIG5vbi16ZXJvIHNpemUgaWYgdGhlIGN1cnJlbnQgc2l6ZSBpcyBudWxsLlxuICpcbiAqIFRoaXMgdHJpY2sgaXMgcmVxdWlyZWQgdG8gbWl0aWdhdGUgdGhlIGZhY3QgdGhhdCB0aGUgc2NyZWVuIGZyYW1lIHR1cm5zIG51bGwgaW4gc29tZSBjYXNlcy5cbiAqIFNlZSBtb3JlIG9uIHRoaXMgYXQgaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9pc3N1ZXMvNTY4XG4gKi9cbmZ1bmN0aW9uIHdhdGNoU2NyZWVuRnJhbWUoKSB7XG4gICAgaWYgKHNjcmVlbkZyYW1lU2l6ZVRpbWVvdXRJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY2hlY2tTY3JlZW5GcmFtZSA9ICgpID0+IHtcbiAgICAgICAgY29uc3QgZnJhbWVTaXplID0gZ2V0Q3VycmVudFNjcmVlbkZyYW1lKCk7XG4gICAgICAgIGlmIChpc0ZyYW1lU2l6ZU51bGwoZnJhbWVTaXplKSkge1xuICAgICAgICAgICAgc2NyZWVuRnJhbWVTaXplVGltZW91dElkID0gc2V0VGltZW91dChjaGVja1NjcmVlbkZyYW1lLCBzY3JlZW5GcmFtZUNoZWNrSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2NyZWVuRnJhbWVCYWNrdXAgPSBmcmFtZVNpemU7XG4gICAgICAgICAgICBzY3JlZW5GcmFtZVNpemVUaW1lb3V0SWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNoZWNrU2NyZWVuRnJhbWUoKTtcbn1cbi8qKlxuICogQSB2ZXJzaW9uIG9mIHRoZSBlbnRyb3B5IHNvdXJjZSB3aXRob3V0IHN0YWJpbGl6YXRpb24uXG4gKlxuICogV2FybmluZyBmb3IgcGFja2FnZSB1c2VyczpcbiAqIFRoaXMgZnVuY3Rpb24gaXMgb3V0IG9mIFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gY2FuIGNoYW5nZSB1bmV4cGVjdGVkbHkuIFVzYWdlIGlzIGF0IHlvdXIgb3duIHJpc2suXG4gKi9cbmZ1bmN0aW9uIGdldFVuc3RhYmxlU2NyZWVuRnJhbWUoKSB7XG4gICAgd2F0Y2hTY3JlZW5GcmFtZSgpO1xuICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGxldCBmcmFtZVNpemUgPSBnZXRDdXJyZW50U2NyZWVuRnJhbWUoKTtcbiAgICAgICAgaWYgKGlzRnJhbWVTaXplTnVsbChmcmFtZVNpemUpKSB7XG4gICAgICAgICAgICBpZiAoc2NyZWVuRnJhbWVCYWNrdXApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gWy4uLnNjcmVlbkZyYW1lQmFja3VwXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChnZXRGdWxsc2NyZWVuRWxlbWVudCgpKSB7XG4gICAgICAgICAgICAgICAgLy8gU29tZSBicm93c2VycyBzZXQgdGhlIHNjcmVlbiBmcmFtZSB0byB6ZXJvIHdoZW4gcHJvZ3JhbW1hdGljIGZ1bGxzY3JlZW4gaXMgb24uXG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgYSBjaGFuY2Ugb2YgZ2V0dGluZyBhIG5vbi16ZXJvIGZyYW1lIGFmdGVyIGV4aXRpbmcgdGhlIGZ1bGxzY3JlZW4uXG4gICAgICAgICAgICAgICAgLy8gU2VlIG1vcmUgb24gdGhpcyBhdCBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2lzc3Vlcy81NjhcbiAgICAgICAgICAgICAgICBhd2FpdCBleGl0RnVsbHNjcmVlbigpO1xuICAgICAgICAgICAgICAgIGZyYW1lU2l6ZSA9IGdldEN1cnJlbnRTY3JlZW5GcmFtZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghaXNGcmFtZVNpemVOdWxsKGZyYW1lU2l6ZSkpIHtcbiAgICAgICAgICAgIHNjcmVlbkZyYW1lQmFja3VwID0gZnJhbWVTaXplO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmcmFtZVNpemU7XG4gICAgfTtcbn1cbi8qKlxuICogQSB2ZXJzaW9uIG9mIHRoZSBlbnRyb3B5IHNvdXJjZSB3aXRoIHN0YWJpbGl6YXRpb24gdG8gbWFrZSBpdCBzdWl0YWJsZSBmb3Igc3RhdGljIGZpbmdlcnByaW50aW5nLlxuICpcbiAqIFNvbWV0aW1lcyB0aGUgYXZhaWxhYmxlIHNjcmVlbiByZXNvbHV0aW9uIGNoYW5nZXMgYSBiaXQsIGUuZy4gMTkwMHgxNDQwIFx1MjE5MiAxOTAweDE0MzkuIEEgcG9zc2libGUgcmVhc29uOiBtYWNPUyBEb2NrXG4gKiBzaHJpbmtzIHRvIGZpdCBtb3JlIGljb25zIHdoZW4gdGhlcmUgaXMgdG9vIGxpdHRsZSBzcGFjZS4gVGhlIHJvdW5kaW5nIGlzIHVzZWQgdG8gbWl0aWdhdGUgdGhlIGRpZmZlcmVuY2UuXG4gKlxuICogVGhlIGZyYW1lIHdpZHRoIGlzIGFsd2F5cyAwIGluIHByaXZhdGUgbW9kZSBvZiBTYWZhcmkgMTcsIHNvIHRoZSBmcmFtZSBpcyBub3QgdXNlZCBpbiBTYWZhcmkgMTcuXG4gKi9cbmZ1bmN0aW9uIGdldFNjcmVlbkZyYW1lKCkge1xuICAgIGlmIChpc1dlYktpdCgpICYmIGlzV2ViS2l0NjE2T3JOZXdlcigpICYmIGlzU2FmYXJpV2ViS2l0KCkpIHtcbiAgICAgICAgcmV0dXJuICgpID0+IFByb21pc2UucmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgIH1cbiAgICBjb25zdCBzY3JlZW5GcmFtZUdldHRlciA9IGdldFVuc3RhYmxlU2NyZWVuRnJhbWUoKTtcbiAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBmcmFtZVNpemUgPSBhd2FpdCBzY3JlZW5GcmFtZUdldHRlcigpO1xuICAgICAgICBjb25zdCBwcm9jZXNzU2l6ZSA9IChzaWRlU2l6ZSkgPT4gKHNpZGVTaXplID09PSBudWxsID8gbnVsbCA6IHJvdW5kKHNpZGVTaXplLCByb3VuZGluZ1ByZWNpc2lvbikpO1xuICAgICAgICAvLyBJdCBtaWdodCBsb29rIGxpa2UgSSBkb24ndCBrbm93IGFib3V0IGBmb3JgIGFuZCBgbWFwYC5cbiAgICAgICAgLy8gSW4gZmFjdCwgc3VjaCBjb2RlIGlzIHVzZWQgdG8gYXZvaWQgVHlwZVNjcmlwdCBpc3N1ZXMgd2l0aG91dCB1c2luZyBgYXNgLlxuICAgICAgICByZXR1cm4gW3Byb2Nlc3NTaXplKGZyYW1lU2l6ZVswXSksIHByb2Nlc3NTaXplKGZyYW1lU2l6ZVsxXSksIHByb2Nlc3NTaXplKGZyYW1lU2l6ZVsyXSksIHByb2Nlc3NTaXplKGZyYW1lU2l6ZVszXSldO1xuICAgIH07XG59XG5mdW5jdGlvbiBnZXRDdXJyZW50U2NyZWVuRnJhbWUoKSB7XG4gICAgY29uc3QgcyA9IHNjcmVlbjtcbiAgICAvLyBTb21lIGJyb3dzZXJzIHJldHVybiBzY3JlZW4gcmVzb2x1dGlvbiBhcyBzdHJpbmdzLCBlLmcuIFwiMTIwMFwiLCBpbnN0ZWFkIG9mIGEgbnVtYmVyLCBlLmcuIDEyMDAuXG4gICAgLy8gSSBzdXNwZWN0IGl0J3MgZG9uZSBieSBjZXJ0YWluIHBsdWdpbnMgdGhhdCByYW5kb21pemUgYnJvd3NlciBwcm9wZXJ0aWVzIHRvIHByZXZlbnQgZmluZ2VycHJpbnRpbmcuXG4gICAgLy9cbiAgICAvLyBTb21lIGJyb3dzZXJzIChJRSwgRWRnZSBcdTIyNjQxOCkgZG9uJ3QgcHJvdmlkZSBgc2NyZWVuLmF2YWlsTGVmdGAgYW5kIGBzY3JlZW4uYXZhaWxUb3BgLiBUaGUgcHJvcGVydHkgdmFsdWVzIGFyZVxuICAgIC8vIHJlcGxhY2VkIHdpdGggMCBpbiBzdWNoIGNhc2VzIHRvIG5vdCBsb3NlIHRoZSBlbnRyb3B5IGZyb20gYHNjcmVlbi5hdmFpbFdpZHRoYCBhbmQgYHNjcmVlbi5hdmFpbEhlaWdodGAuXG4gICAgcmV0dXJuIFtcbiAgICAgICAgcmVwbGFjZU5hTih0b0Zsb2F0KHMuYXZhaWxUb3ApLCBudWxsKSxcbiAgICAgICAgcmVwbGFjZU5hTih0b0Zsb2F0KHMud2lkdGgpIC0gdG9GbG9hdChzLmF2YWlsV2lkdGgpIC0gcmVwbGFjZU5hTih0b0Zsb2F0KHMuYXZhaWxMZWZ0KSwgMCksIG51bGwpLFxuICAgICAgICByZXBsYWNlTmFOKHRvRmxvYXQocy5oZWlnaHQpIC0gdG9GbG9hdChzLmF2YWlsSGVpZ2h0KSAtIHJlcGxhY2VOYU4odG9GbG9hdChzLmF2YWlsVG9wKSwgMCksIG51bGwpLFxuICAgICAgICByZXBsYWNlTmFOKHRvRmxvYXQocy5hdmFpbExlZnQpLCBudWxsKSxcbiAgICBdO1xufVxuZnVuY3Rpb24gaXNGcmFtZVNpemVOdWxsKGZyYW1lU2l6ZSkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgKytpKSB7XG4gICAgICAgIGlmIChmcmFtZVNpemVbaV0pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZ2V0SGFyZHdhcmVDb25jdXJyZW5jeSgpIHtcbiAgICAvLyBzb21ldGltZXMgaGFyZHdhcmUgY29uY3VycmVuY3kgaXMgYSBzdHJpbmdcbiAgICByZXR1cm4gcmVwbGFjZU5hTih0b0ludChuYXZpZ2F0b3IuaGFyZHdhcmVDb25jdXJyZW5jeSksIHVuZGVmaW5lZCk7XG59XG5cbmZ1bmN0aW9uIGdldFRpbWV6b25lKCkge1xuICAgIHZhciBfYTtcbiAgICBjb25zdCBEYXRlVGltZUZvcm1hdCA9IChfYSA9IHdpbmRvdy5JbnRsKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuRGF0ZVRpbWVGb3JtYXQ7XG4gICAgaWYgKERhdGVUaW1lRm9ybWF0KSB7XG4gICAgICAgIGNvbnN0IHRpbWV6b25lID0gbmV3IERhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG4gICAgICAgIGlmICh0aW1lem9uZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRpbWV6b25lO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIEZvciBicm93c2VycyB0aGF0IGRvbid0IHN1cHBvcnQgdGltZXpvbmUgbmFtZXNcbiAgICAvLyBUaGUgbWludXMgaXMgaW50ZW50aW9uYWwgYmVjYXVzZSB0aGUgSlMgb2Zmc2V0IGlzIG9wcG9zaXRlIHRvIHRoZSByZWFsIG9mZnNldFxuICAgIGNvbnN0IG9mZnNldCA9IC1nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgIHJldHVybiBgVVRDJHtvZmZzZXQgPj0gMCA/ICcrJyA6ICcnfSR7b2Zmc2V0fWA7XG59XG5mdW5jdGlvbiBnZXRUaW1lem9uZU9mZnNldCgpIHtcbiAgICBjb25zdCBjdXJyZW50WWVhciA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKTtcbiAgICAvLyBUaGUgdGltZXpvbmUgb2Zmc2V0IG1heSBjaGFuZ2Ugb3ZlciB0aW1lIGR1ZSB0byBkYXlsaWdodCBzYXZpbmcgdGltZSAoRFNUKSBzaGlmdHMuXG4gICAgLy8gVGhlIG5vbi1EU1QgdGltZXpvbmUgb2Zmc2V0IGlzIHVzZWQgYXMgdGhlIHJlc3VsdCB0aW1lem9uZSBvZmZzZXQuXG4gICAgLy8gU2luY2UgdGhlIERTVCBzZWFzb24gZGlmZmVycyBpbiB0aGUgbm9ydGhlcm4gYW5kIHRoZSBzb3V0aGVybiBoZW1pc3BoZXJlcyxcbiAgICAvLyBib3RoIEphbnVhcnkgYW5kIEp1bHkgdGltZXpvbmVzIG9mZnNldHMgYXJlIGNvbnNpZGVyZWQuXG4gICAgcmV0dXJuIE1hdGgubWF4KFxuICAgIC8vIGBnZXRUaW1lem9uZU9mZnNldGAgcmV0dXJucyBhIG51bWJlciBhcyBhIHN0cmluZyBpbiBzb21lIHVuaWRlbnRpZmllZCBjYXNlc1xuICAgIHRvRmxvYXQobmV3IERhdGUoY3VycmVudFllYXIsIDAsIDEpLmdldFRpbWV6b25lT2Zmc2V0KCkpLCB0b0Zsb2F0KG5ldyBEYXRlKGN1cnJlbnRZZWFyLCA2LCAxKS5nZXRUaW1lem9uZU9mZnNldCgpKSk7XG59XG5cbmZ1bmN0aW9uIGdldFNlc3Npb25TdG9yYWdlKCkge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiAhIXdpbmRvdy5zZXNzaW9uU3RvcmFnZTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8qIFNlY3VyaXR5RXJyb3Igd2hlbiByZWZlcmVuY2luZyBpdCBtZWFucyBpdCBleGlzdHMgKi9cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuXG4vLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD03ODE0NDdcbmZ1bmN0aW9uIGdldExvY2FsU3RvcmFnZSgpIHtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gISF3aW5kb3cubG9jYWxTdG9yYWdlO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICAvKiBTZWN1cml0eUVycm9yIHdoZW4gcmVmZXJlbmNpbmcgaXQgbWVhbnMgaXQgZXhpc3RzICovXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0SW5kZXhlZERCKCkge1xuICAgIC8vIElFIGFuZCBFZGdlIGRvbid0IGFsbG93IGFjY2Vzc2luZyBpbmRleGVkREIgaW4gcHJpdmF0ZSBtb2RlLCB0aGVyZWZvcmUgSUUgYW5kIEVkZ2Ugd2lsbCBoYXZlIGRpZmZlcmVudFxuICAgIC8vIHZpc2l0b3IgaWRlbnRpZmllciBpbiBub3JtYWwgYW5kIHByaXZhdGUgbW9kZXMuXG4gICAgaWYgKGlzVHJpZGVudCgpIHx8IGlzRWRnZUhUTUwoKSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gISF3aW5kb3cuaW5kZXhlZERCO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICAvKiBTZWN1cml0eUVycm9yIHdoZW4gcmVmZXJlbmNpbmcgaXQgbWVhbnMgaXQgZXhpc3RzICovXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0T3BlbkRhdGFiYXNlKCkge1xuICAgIHJldHVybiAhIXdpbmRvdy5vcGVuRGF0YWJhc2U7XG59XG5cbmZ1bmN0aW9uIGdldENwdUNsYXNzKCkge1xuICAgIHJldHVybiBuYXZpZ2F0b3IuY3B1Q2xhc3M7XG59XG5cbmZ1bmN0aW9uIGdldFBsYXRmb3JtKCkge1xuICAgIC8vIEFuZHJvaWQgQ2hyb21lIDg2IGFuZCA4NyBhbmQgQW5kcm9pZCBGaXJlZm94IDgwIGFuZCA4NCBkb24ndCBtb2NrIHRoZSBwbGF0Zm9ybSB2YWx1ZSB3aGVuIGRlc2t0b3AgbW9kZSBpcyByZXF1ZXN0ZWRcbiAgICBjb25zdCB7IHBsYXRmb3JtIH0gPSBuYXZpZ2F0b3I7XG4gICAgLy8gaU9TIG1vY2tzIHRoZSBwbGF0Zm9ybSB2YWx1ZSB3aGVuIGRlc2t0b3AgdmVyc2lvbiBpcyByZXF1ZXN0ZWQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9maW5nZXJwcmludGpzL2ZpbmdlcnByaW50anMvaXNzdWVzLzUxNFxuICAgIC8vIGlQYWQgdXNlcyBkZXNrdG9wIG1vZGUgYnkgZGVmYXVsdCBzaW5jZSBpT1MgMTNcbiAgICAvLyBUaGUgdmFsdWUgaXMgJ01hY0ludGVsJyBvbiBNMSBNYWNzXG4gICAgLy8gVGhlIHZhbHVlIGlzICdpUGhvbmUnIG9uIGlQb2QgVG91Y2hcbiAgICBpZiAocGxhdGZvcm0gPT09ICdNYWNJbnRlbCcpIHtcbiAgICAgICAgaWYgKGlzV2ViS2l0KCkgJiYgIWlzRGVza3RvcFdlYktpdCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNJUGFkKCkgPyAnaVBhZCcgOiAnaVBob25lJztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGxhdGZvcm07XG59XG5cbmZ1bmN0aW9uIGdldFZlbmRvcigpIHtcbiAgICByZXR1cm4gbmF2aWdhdG9yLnZlbmRvciB8fCAnJztcbn1cblxuLyoqXG4gKiBDaGVja3MgZm9yIGJyb3dzZXItc3BlY2lmaWMgKG5vdCBlbmdpbmUgc3BlY2lmaWMpIGdsb2JhbCB2YXJpYWJsZXMgdG8gdGVsbCBicm93c2VycyB3aXRoIHRoZSBzYW1lIGVuZ2luZSBhcGFydC5cbiAqIE9ubHkgc29tZXdoYXQgcG9wdWxhciBicm93c2VycyBhcmUgY29uc2lkZXJlZC5cbiAqL1xuZnVuY3Rpb24gZ2V0VmVuZG9yRmxhdm9ycygpIHtcbiAgICBjb25zdCBmbGF2b3JzID0gW107XG4gICAgZm9yIChjb25zdCBrZXkgb2YgW1xuICAgICAgICAvLyBCbGluayBhbmQgc29tZSBicm93c2VycyBvbiBpT1NcbiAgICAgICAgJ2Nocm9tZScsXG4gICAgICAgIC8vIFNhZmFyaSBvbiBtYWNPU1xuICAgICAgICAnc2FmYXJpJyxcbiAgICAgICAgLy8gQ2hyb21lIG9uIGlPUyAoY2hlY2tlZCBpbiA4NSBvbiAxMyBhbmQgODcgb24gMTQpXG4gICAgICAgICdfX2NyV2ViJyxcbiAgICAgICAgJ19fZ0NyV2ViJyxcbiAgICAgICAgLy8gWWFuZGV4IEJyb3dzZXIgb24gaU9TLCBtYWNPUyBhbmQgQW5kcm9pZCAoY2hlY2tlZCBpbiAyMS4yIG9uIGlPUyAxNCwgbWFjT1MgYW5kIEFuZHJvaWQpXG4gICAgICAgICd5YW5kZXgnLFxuICAgICAgICAvLyBZYW5kZXggQnJvd3NlciBvbiBpT1MgKGNoZWNrZWQgaW4gMjEuMiBvbiAxNClcbiAgICAgICAgJ19feWInLFxuICAgICAgICAnX195YnJvJyxcbiAgICAgICAgLy8gRmlyZWZveCBvbiBpT1MgKGNoZWNrZWQgaW4gMzIgb24gMTQpXG4gICAgICAgICdfX2ZpcmVmb3hfXycsXG4gICAgICAgIC8vIEVkZ2Ugb24gaU9TIChjaGVja2VkIGluIDQ2IG9uIDE0KVxuICAgICAgICAnX19lZGdlVHJhY2tpbmdQcmV2ZW50aW9uU3RhdGlzdGljcycsXG4gICAgICAgICd3ZWJraXQnLFxuICAgICAgICAvLyBPcGVyYSBUb3VjaCBvbiBpT1MgKGNoZWNrZWQgaW4gMi42IG9uIDE0KVxuICAgICAgICAnb3BydCcsXG4gICAgICAgIC8vIFNhbXN1bmcgSW50ZXJuZXQgb24gQW5kcm9pZCAoY2hlY2tlZCBpbiAxMS4xKVxuICAgICAgICAnc2Ftc3VuZ0FyJyxcbiAgICAgICAgLy8gVUMgQnJvd3NlciBvbiBBbmRyb2lkIChjaGVja2VkIGluIDEyLjEwIGFuZCAxMy4wKVxuICAgICAgICAndWN3ZWInLFxuICAgICAgICAnVUNTaGVsbEphdmEnLFxuICAgICAgICAvLyBQdWZmaW4gb24gQW5kcm9pZCAoY2hlY2tlZCBpbiA5LjApXG4gICAgICAgICdwdWZmaW5EZXZpY2UnLFxuICAgICAgICAvLyBVQyBvbiBpT1MgYW5kIE9wZXJhIG9uIEFuZHJvaWQgaGF2ZSBubyBzcGVjaWZpYyBnbG9iYWwgdmFyaWFibGVzXG4gICAgICAgIC8vIEVkZ2UgZm9yIEFuZHJvaWQgaXNuJ3QgY2hlY2tlZFxuICAgIF0pIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB3aW5kb3dba2V5XTtcbiAgICAgICAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGZsYXZvcnMucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmbGF2b3JzLnNvcnQoKTtcbn1cblxuLyoqXG4gKiBuYXZpZ2F0b3IuY29va2llRW5hYmxlZCBjYW5ub3QgZGV0ZWN0IGN1c3RvbSBvciBudWFuY2VkIGNvb2tpZSBibG9ja2luZyBjb25maWd1cmF0aW9ucy4gRm9yIGV4YW1wbGUsIHdoZW4gYmxvY2tpbmdcbiAqIGNvb2tpZXMgdmlhIHRoZSBBZHZhbmNlZCBQcml2YWN5IFNldHRpbmdzIGluIElFOSwgaXQgYWx3YXlzIHJldHVybnMgdHJ1ZS4gQW5kIHRoZXJlIGhhdmUgYmVlbiBpc3N1ZXMgaW4gdGhlIHBhc3Qgd2l0aFxuICogc2l0ZS1zcGVjaWZpYyBleGNlcHRpb25zLiBEb24ndCByZWx5IG9uIGl0LlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL01vZGVybml6ci9Nb2Rlcm5penIvYmxvYi9tYXN0ZXIvZmVhdHVyZS1kZXRlY3RzL2Nvb2tpZXMuanMgVGFrZW4gZnJvbSBoZXJlXG4gKi9cbmZ1bmN0aW9uIGFyZUNvb2tpZXNFbmFibGVkKCkge1xuICAgIGNvbnN0IGQgPSBkb2N1bWVudDtcbiAgICAvLyBUYWtlbiBmcm9tIGhlcmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9Nb2Rlcm5penIvTW9kZXJuaXpyL2Jsb2IvbWFzdGVyL2ZlYXR1cmUtZGV0ZWN0cy9jb29raWVzLmpzXG4gICAgLy8gbmF2aWdhdG9yLmNvb2tpZUVuYWJsZWQgY2Fubm90IGRldGVjdCBjdXN0b20gb3IgbnVhbmNlZCBjb29raWUgYmxvY2tpbmcgY29uZmlndXJhdGlvbnMuIEZvciBleGFtcGxlLCB3aGVuIGJsb2NraW5nXG4gICAgLy8gY29va2llcyB2aWEgdGhlIEFkdmFuY2VkIFByaXZhY3kgU2V0dGluZ3MgaW4gSUU5LCBpdCBhbHdheXMgcmV0dXJucyB0cnVlLiBBbmQgdGhlcmUgaGF2ZSBiZWVuIGlzc3VlcyBpbiB0aGUgcGFzdFxuICAgIC8vIHdpdGggc2l0ZS1zcGVjaWZpYyBleGNlcHRpb25zLiBEb24ndCByZWx5IG9uIGl0LlxuICAgIC8vIHRyeS4uY2F0Y2ggYmVjYXVzZSBzb21lIGluIHNpdHVhdGlvbnMgYGRvY3VtZW50LmNvb2tpZWAgaXMgZXhwb3NlZCBidXQgdGhyb3dzIGFcbiAgICAvLyBTZWN1cml0eUVycm9yIGlmIHlvdSB0cnkgdG8gYWNjZXNzIGl0OyBlLmcuIGRvY3VtZW50cyBjcmVhdGVkIGZyb20gZGF0YSBVUklzXG4gICAgLy8gb3IgaW4gc2FuZGJveGVkIGlmcmFtZXMgKGRlcGVuZGluZyBvbiBmbGFncy9jb250ZXh0KVxuICAgIHRyeSB7XG4gICAgICAgIC8vIENyZWF0ZSBjb29raWVcbiAgICAgICAgZC5jb29raWUgPSAnY29va2lldGVzdD0xOyBTYW1lU2l0ZT1TdHJpY3Q7JztcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gZC5jb29raWUuaW5kZXhPZignY29va2lldGVzdD0nKSAhPT0gLTE7XG4gICAgICAgIC8vIERlbGV0ZSBjb29raWVcbiAgICAgICAgZC5jb29raWUgPSAnY29va2lldGVzdD0xOyBTYW1lU2l0ZT1TdHJpY3Q7IGV4cGlyZXM9VGh1LCAwMS1KYW4tMTk3MCAwMDowMDowMSBHTVQnO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG4vKipcbiAqIE9ubHkgc2luZ2xlIGVsZW1lbnQgc2VsZWN0b3IgYXJlIHN1cHBvcnRlZCAobm8gb3BlcmF0b3JzIGxpa2Ugc3BhY2UsICssID4sIGV0YykuXG4gKiBgZW1iZWRgIGFuZCBgcG9zaXRpb246IGZpeGVkO2Agd2lsbCBiZSBjb25zaWRlcmVkIGFzIGJsb2NrZWQgYW55d2F5IGJlY2F1c2UgaXQgYWx3YXlzIGhhcyBubyBvZmZzZXRQYXJlbnQuXG4gKiBBdm9pZCBgaWZyYW1lYCBhbmQgYW55dGhpbmcgd2l0aCBgW3NyYz1dYCBiZWNhdXNlIHRoZXkgcHJvZHVjZSBleGNlc3MgSFRUUCByZXF1ZXN0cy5cbiAqXG4gKiBUaGUgXCJpbmFwcHJvcHJpYXRlXCIgc2VsZWN0b3JzIGFyZSBvYmZ1c2NhdGVkLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZpbmdlcnByaW50anMvZmluZ2VycHJpbnRqcy9pc3N1ZXMvNzM0LlxuICogQSBmdW5jdGlvbiBpcyB1c2VkIGluc3RlYWQgb2YgYSBwbGFpbiBvYmplY3QgdG8gaGVscCB0cmVlLXNoYWtpbmcuXG4gKlxuICogVGhlIGZ1bmN0aW9uIGNvZGUgaXMgZ2VuZXJhdGVkIGF1dG9tYXRpY2FsbHkuIFNlZSBkb2NzL2NvbnRlbnRfYmxvY2tlcnMubWQgdG8gbGVhcm4gaG93IHRvIG1ha2UgdGhlIGxpc3QuXG4gKi9cbmZ1bmN0aW9uIGdldEZpbHRlcnMoKSB7XG4gICAgY29uc3QgZnJvbUI2NCA9IGF0b2I7IC8vIEp1c3QgZm9yIGJldHRlciBtaW5pZmljYXRpb25cbiAgICByZXR1cm4ge1xuICAgICAgICBhYnBJbmRvOiBbXG4gICAgICAgICAgICAnI0lrbGFuLU1lbGF5YW5nJyxcbiAgICAgICAgICAgICcjS29sb20tSWtsYW4tNzI4JyxcbiAgICAgICAgICAgICcjU2lkZWJhcklrbGFuLXdyYXBwZXInLFxuICAgICAgICAgICAgJ1t0aXRsZT1cIkFMSUVOQk9MQVwiIGldJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kwSnZlQzFDWVc1dVpYSXRZV1J6JyksXG4gICAgICAgIF0sXG4gICAgICAgIGFicHZuOiBbJy5xdWFuZ2NhbycsICcjbW9iaWxlQ2F0ZmlzaCcsIGZyb21CNjQoJ0xtTnNiM05sTFdGa2N3PT0nKSwgJ1tpZF49XCJibl9ib3R0b21fZml4ZWRfXCJdJywgJyNwbWFkdiddLFxuICAgICAgICBhZEJsb2NrRmlubGFuZDogW1xuICAgICAgICAgICAgJy5tYWlub3N0aWxhJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0xuTndiMjV6YjNKcGRBPT0nKSxcbiAgICAgICAgICAgICcueWxhbWFpbm9zJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtS2owaUwyTnNhV05yZEdoeVoyZ3VZWE53UHlKZCcpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNITTZMeTloY0hBdWNtVmhaSEJsWVdzdVkyOXRMMkZrY3lKZCcpLFxuICAgICAgICBdLFxuICAgICAgICBhZEJsb2NrUGVyc2lhbjogW1xuICAgICAgICAgICAgJyNuYXZiYXJfbm90aWNlXzUwJyxcbiAgICAgICAgICAgICcua2FkcicsXG4gICAgICAgICAgICAnVEFCTEVbd2lkdGg9XCIxNDBweFwiXScsXG4gICAgICAgICAgICAnI2RpdkFnYWhpJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtWGowaWFIUjBjRG92TDJjeExuWXVabmR0Y20wdWJtVjBMMkZrTHlKZCcpLFxuICAgICAgICBdLFxuICAgICAgICBhZEJsb2NrV2FybmluZ1JlbW92YWw6IFtcbiAgICAgICAgICAgICcjYWRibG9jay1ob25leXBvdCcsXG4gICAgICAgICAgICAnLmFkYmxvY2tlci1yb290JyxcbiAgICAgICAgICAgICcud3BfYWRibG9ja19kZXRlY3QnLFxuICAgICAgICAgICAgZnJvbUI2NCgnTG1obFlXUmxjaTFpYkc5amEyVmtMV0ZrJyksXG4gICAgICAgICAgICBmcm9tQjY0KCdJMkZrWDJKc2IyTnJaWEk9JyksXG4gICAgICAgIF0sXG4gICAgICAgIGFkR3VhcmRBbm5veWFuY2VzOiBbXG4gICAgICAgICAgICAnLmhzLXNvc3lhbCcsXG4gICAgICAgICAgICAnI2Nvb2tpZWNvbnNlbnRkaXYnLFxuICAgICAgICAgICAgJ2RpdltjbGFzc149XCJhcHBfZ2RwclwiXScsXG4gICAgICAgICAgICAnLmFzLW9pbCcsXG4gICAgICAgICAgICAnW2RhdGEtY3lwcmVzcz1cInNvZnQtcHVzaC1ub3RpZmljYXRpb24tbW9kYWxcIl0nLFxuICAgICAgICBdLFxuICAgICAgICBhZEd1YXJkQmFzZTogW1xuICAgICAgICAgICAgJy5CZXR0ZXJKc1BvcE92ZXJsYXknLFxuICAgICAgICAgICAgZnJvbUI2NCgnSTJGa1h6TXdNRmd5TlRBPScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnSTJKaGJtNWxjbVpzYjJGME1qST0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kyTmhiWEJoYVdkdUxXSmhibTVsY2c9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnSTBGa0xVTnZiblJsYm5RPScpLFxuICAgICAgICBdLFxuICAgICAgICBhZEd1YXJkQ2hpbmVzZTogW1xuICAgICAgICAgICAgZnJvbUI2NCgnTGxwcFgyRmtYMkZmU0E9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpTG1oMGFHSmxkRE0wTG1OdmJTSmQnKSxcbiAgICAgICAgICAgICcjd2lkZ2V0LXF1YW4nLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpTHpnME9Ua3lNREl3TG5oNWVpSmQnKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtS2owaUxqRTVOVFpvYkM1amIyMHZJbDA9JyksXG4gICAgICAgIF0sXG4gICAgICAgIGFkR3VhcmRGcmVuY2g6IFtcbiAgICAgICAgICAgICcjcGF2ZVB1YicsXG4gICAgICAgICAgICBmcm9tQjY0KCdMbUZrTFdSbGMydDBiM0F0Y21WamRHRnVaMnhsJyksXG4gICAgICAgICAgICAnLm1vYmlsZV9hZGhlc2lvbicsXG4gICAgICAgICAgICAnLndpZGdldGFkdicsXG4gICAgICAgICAgICBmcm9tQjY0KCdMbUZrYzE5aVlXND0nKSxcbiAgICAgICAgXSxcbiAgICAgICAgYWRHdWFyZEdlcm1hbjogWydhc2lkZVtkYXRhLXBvcnRhbC1pZD1cImxlYWRlcmJvYXJkXCJdJ10sXG4gICAgICAgIGFkR3VhcmRKYXBhbmVzZTogW1xuICAgICAgICAgICAgJyNrYXVsaV95YWRfMScsXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0RvdkwyRmtNaTUwY21GbVptbGpaMkYwWlM1dVpYUXZJbDA9JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdMbDl3YjNCSmJsOXBibVpwYm1sMFpWOWhaQT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdMbUZrWjI5dloyeGwnKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0xsOWZhWE5pYjI5emRGSmxkSFZ5YmtGaycpLFxuICAgICAgICBdLFxuICAgICAgICBhZEd1YXJkTW9iaWxlOiBbXG4gICAgICAgICAgICBmcm9tQjY0KCdZVzF3TFdGMWRHOHRZV1J6JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdMbUZ0Y0Y5aFpBPT0nKSxcbiAgICAgICAgICAgICdhbXAtZW1iZWRbdHlwZT1cIjI0c21pXCJdJyxcbiAgICAgICAgICAgICcjbWdpZF9pZnJhbWUxJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kyRmtYMmx1ZG1sbGQxOWhjbVZoJyksXG4gICAgICAgIF0sXG4gICAgICAgIGFkR3VhcmRSdXNzaWFuOiBbXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0hNNkx5OWhaQzVzWlhSdFpXRmtjeTVqYjIwdklsMD0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0xuSmxZMnhoYldFPScpLFxuICAgICAgICAgICAgJ2RpdltpZF49XCJzbWkyYWRibG9ja1wiXScsXG4gICAgICAgICAgICBmcm9tQjY0KCdaR2wyVzJsa1hqMGlRV1JHYjNoZlltRnVibVZ5WHlKZCcpLFxuICAgICAgICAgICAgJyNwc3lkdWNrcG9ja2ViYWxsJyxcbiAgICAgICAgXSxcbiAgICAgICAgYWRHdWFyZFNvY2lhbDogW1xuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpTHk5M2QzY3VjM1IxYldKc1pYVndiMjR1WTI5dEwzTjFZbTFwZEQ5MWNtdzlJbDA9JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlMeTkwWld4bFozSmhiUzV0WlM5emFHRnlaUzkxY213L0lsMD0nKSxcbiAgICAgICAgICAgICcuZXRzeS10d2VldCcsXG4gICAgICAgICAgICAnI2lubGluZVNoYXJlJyxcbiAgICAgICAgICAgICcucG9wdXAtc29jaWFsJyxcbiAgICAgICAgXSxcbiAgICAgICAgYWRHdWFyZFNwYW5pc2hQb3J0dWd1ZXNlOiBbJyNiYXJyYVB1YmxpY2lkYWRlJywgJyNQdWJsaWNpZGFkZScsICcjcHVibGlFc3BlY2lhbCcsICcjcXVlVG9vbHRpcCcsICcuY250LXB1YmxpJ10sXG4gICAgICAgIGFkR3VhcmRUcmFja2luZ1Byb3RlY3Rpb246IFtcbiAgICAgICAgICAgICcjcW9vLWNvdW50ZXInLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNEb3ZMMk5zYVdOckxtaHZkR3h2Wnk1eWRTOGlYUT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0RvdkwyaHBkR052ZFc1MFpYSXVjblV2ZEc5d0wzTjBZWFF1Y0dod0lsMD0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtWGowaWFIUjBjRG92TDNSdmNDNXRZV2xzTG5KMUwycDFiWEFpWFE9PScpLFxuICAgICAgICAgICAgJyN0b3AxMDBjb3VudGVyJyxcbiAgICAgICAgXSxcbiAgICAgICAgYWRHdWFyZFR1cmtpc2g6IFtcbiAgICAgICAgICAgICcjYmFja2thcGF0JyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kzSmxhMnhoYldrPScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNEb3ZMMkZrYzJWeWRpNXZiblJsYXk1amIyMHVkSEl2SWwwPScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNEb3ZMMmw2YkdWdWVta3VZMjl0TDJOaGJYQmhhV2R1THlKZCcpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNEb3ZMM2QzZHk1cGJuTjBZV3hzWVdSekxtNWxkQzhpWFE9PScpLFxuICAgICAgICBdLFxuICAgICAgICBidWxnYXJpYW46IFtmcm9tQjY0KCdkR1FqWm5KbFpXNWxkRjkwWVdKc1pWOWhaSE09JyksICcjZWFfaW50ZXh0X2RpdicsICcubGFwbmktcG9wLW92ZXInLCAnI3hlbml1bV9ob3Rfb2ZmZXJzJ10sXG4gICAgICAgIGVhc3lMaXN0OiBbXG4gICAgICAgICAgICAnLnliLWZsb29yYWQnLFxuICAgICAgICAgICAgZnJvbUI2NCgnTG5kcFpHZGxkRjl3YjE5aFpITmZkMmxrWjJWMCcpLFxuICAgICAgICAgICAgZnJvbUI2NCgnTG5SeVlXWm1hV05xZFc1cmVTMWhaQT09JyksXG4gICAgICAgICAgICAnLnRleHRhZF9oZWFkbGluZScsXG4gICAgICAgICAgICBmcm9tQjY0KCdMbk53YjI1emIzSmxaQzEwWlhoMExXeHBibXR6JyksXG4gICAgICAgIF0sXG4gICAgICAgIGVhc3lMaXN0Q2hpbmE6IFtcbiAgICAgICAgICAgIGZyb21CNjQoJ0xtRndjR2QxYVdSbExYZHlZWEJiYjI1amJHbGpheW85SW1KalpXSnZjeTVqYjIwaVhRPT0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0xtWnliMjUwY0dGblpVRmtkazA9JyksXG4gICAgICAgICAgICAnI3Rhb3Rhb2xlJyxcbiAgICAgICAgICAgICcjYWFmb290LnRvcF9ib3gnLFxuICAgICAgICAgICAgJy5jZmFfcG9wdXAnLFxuICAgICAgICBdLFxuICAgICAgICBlYXN5TGlzdENvb2tpZTogW1xuICAgICAgICAgICAgJy5lem1vYi1mb290ZXInLFxuICAgICAgICAgICAgJy5jYy1Db29raWVXYXJuaW5nJyxcbiAgICAgICAgICAgICdbZGF0YS1jb29raWUtbnVtYmVyXScsXG4gICAgICAgICAgICBmcm9tQjY0KCdMbUYzTFdOdmIydHBaUzFpWVc1dVpYST0nKSxcbiAgICAgICAgICAgICcuc3lnbmFsMjQtZ2Rwci1tb2RhbC13cmFwJyxcbiAgICAgICAgXSxcbiAgICAgICAgZWFzeUxpc3RDemVjaFNsb3ZhazogW1xuICAgICAgICAgICAgJyNvbmxham55LXN0aWNrZXJzJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kzSmxhMnhoYlc1cExXSnZlQT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdMbkpsYTJ4aGJXRXRiV1ZuWVdKdllYSmsnKSxcbiAgICAgICAgICAgICcuc2tsaWsnLFxuICAgICAgICAgICAgZnJvbUI2NCgnVzJsa1hqMGljMnRzYVd0U1pXdHNZVzFoSWwwPScpLFxuICAgICAgICBdLFxuICAgICAgICBlYXN5TGlzdER1dGNoOiBbXG4gICAgICAgICAgICBmcm9tQjY0KCdJMkZrZG1WeWRHVnVkR2xsJyksXG4gICAgICAgICAgICBmcm9tQjY0KCdJM1pwY0VGa2JXRnlhM1JDWVc1dVpYSkNiRzlqYXc9PScpLFxuICAgICAgICAgICAgJy5hZHN0ZWtzdCcsXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0hNNkx5OTRiSFIxWW1VdWJtd3ZZMnhwWTJzdklsMD0nKSxcbiAgICAgICAgICAgICcjc2VtaWxvLWxyZWN0YW5nbGUnLFxuICAgICAgICBdLFxuICAgICAgICBlYXN5TGlzdEdlcm1hbnk6IFtcbiAgICAgICAgICAgICcjU1Nwb3RJTVBvcFNsaWRlcicsXG4gICAgICAgICAgICBmcm9tQjY0KCdMbk53YjI1emIzSnNhVzVyWjNKMVpXND0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kzZGxjbUoxYm1kemEzaz0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kzSmxhMnhoYldVdGNtVmphSFJ6TFcxcGRIUmwnKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtWGowaWFIUjBjSE02THk5aVpEYzBNaTVqYjIwdklsMD0nKSxcbiAgICAgICAgXSxcbiAgICAgICAgZWFzeUxpc3RJdGFseTogW1xuICAgICAgICAgICAgZnJvbUI2NCgnTG1KdmVGOWhaSFpmWVc1dWRXNWphUT09JyksXG4gICAgICAgICAgICAnLnNiLWJveC1wdWJibGlyZWRhemlvbmFsZScsXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0RvdkwyRm1abWxzYVdGNmFXOXVhV0ZrY3k1emJtRnBMbWwwTHlKZCcpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNITTZMeTloWkhObGNuWmxjaTVvZEcxc0xtbDBMeUpkJyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0hNNkx5OWhabVpwYkdsaGVtbHZibWxoWkhNdWMyNWhhUzVwZEM4aVhRPT0nKSxcbiAgICAgICAgXSxcbiAgICAgICAgZWFzeUxpc3RMaXRodWFuaWE6IFtcbiAgICAgICAgICAgIGZyb21CNjQoJ0xuSmxhMnhoYlc5elgzUmhjbkJoY3c9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnTG5KbGEyeGhiVzl6WDI1MWIzSnZaRzl6JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdhVzFuVzJGc2REMGlVbVZyYkdGdGFXNXBjeUJ6YTNsa1pXeHBjeUpkJyksXG4gICAgICAgICAgICBmcm9tQjY0KCdhVzFuVzJGc2REMGlSR1ZrYVd0MWIzUnBMbXgwSUhObGNuWmxjbWxoYVNKZCcpLFxuICAgICAgICAgICAgZnJvbUI2NCgnYVcxblcyRnNkRDBpU0c5emRHbHVaMkZ6SUZObGNuWmxjbWxoYVM1c2RDSmQnKSxcbiAgICAgICAgXSxcbiAgICAgICAgZXN0b25pYW46IFtmcm9tQjY0KCdRVnRvY21WbUtqMGlhSFIwY0RvdkwzQmhlVFJ5WlhOMWJIUnpNalF1WlhVaVhRPT0nKV0sXG4gICAgICAgIGZhbmJveUFubm95YW5jZXM6IFsnI2FjLWxyZS1wbGF5ZXInLCAnLm5hdmlnYXRlLXRvLXRvcCcsICcjc3Vic2NyaWJlX3BvcHVwJywgJy5uZXdzbGV0dGVyX2hvbGRlcicsICcjYmFjay10b3AnXSxcbiAgICAgICAgZmFuYm95QW50aUZhY2Vib29rOiBbJy51dGlsLWJhci1tb2R1bGUtZmlyZWZseS12aXNpYmxlJ10sXG4gICAgICAgIGZhbmJveUVuaGFuY2VkVHJhY2tlcnM6IFtcbiAgICAgICAgICAgICcub3Blbi5wdXNoTW9kYWwnLFxuICAgICAgICAgICAgJyNpc3N1ZW0tbGVha3ktcGF5d2FsbC1hcnRpY2xlcy16ZXJvLXJlbWFpbmluZy1uYWcnLFxuICAgICAgICAgICAgJyNzb3Zybl9jb250YWluZXInLFxuICAgICAgICAgICAgJ2RpdltjbGFzcyQ9XCItaGlkZVwiXVt6b29tcGFnZS1mb250c2l6ZV1bc3R5bGU9XCJkaXNwbGF5OiBibG9jaztcIl0nLFxuICAgICAgICAgICAgJy5CbG9ja05hZ19fQ2FyZCcsXG4gICAgICAgIF0sXG4gICAgICAgIGZhbmJveVNvY2lhbDogWycjRm9sbG93VXMnLCAnI21ldGVvcmVkX3NoYXJlJywgJyNzb2NpYWxfZm9sbG93JywgJy5hcnRpY2xlLXNoYXJlcicsICcuY29tbXVuaXR5X19zb2NpYWwtZGVzYyddLFxuICAgICAgICBmcmVsbHdpdFN3ZWRpc2g6IFtcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtS2owaVkyRnphVzV2Y0hKdkxuTmxJbDFiZEdGeVoyVjBQU0pmWW14aGJtc2lYUT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbUtqMGlaRzlyZEc5eUxYTmxMbTl1Wld4cGJtc3ViV1VpWFE9PScpLFxuICAgICAgICAgICAgJ2FydGljbGUuY2F0ZWdvcnktc2FtYXJiZXRlJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ1pHbDJMbWh2Ykdsa1FXUnonKSxcbiAgICAgICAgICAgICd1bC5hZHNtb2Rlcm4nLFxuICAgICAgICBdLFxuICAgICAgICBncmVla0FkQmxvY2s6IFtcbiAgICAgICAgICAgIGZyb21CNjQoJ1FWdG9jbVZtS2owaVlXUnRZVzR1YjNSbGJtVjBMbWR5TDJOc2FXTnJQeUpkJyksXG4gICAgICAgICAgICBmcm9tQjY0KCdRVnRvY21WbUtqMGlhSFIwY0RvdkwyRjRhV0ZpWVc1dVpYSnpMbVY0YjJSMWN5NW5jaThpWFE9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnUVZ0b2NtVm1LajBpYUhSMGNEb3ZMMmx1ZEdWeVlXTjBhWFpsTG1admNuUm9ibVYwTG1keUwyTnNhV05yUHlKZCcpLFxuICAgICAgICAgICAgJ0RJVi5hZ29yZXMzMDAnLFxuICAgICAgICAgICAgJ1RBQkxFLmFkdnJpZ2h0JyxcbiAgICAgICAgXSxcbiAgICAgICAgaHVuZ2FyaWFuOiBbXG4gICAgICAgICAgICAnI2NlbXBfZG9ib3onLFxuICAgICAgICAgICAgJy5vcHRpbW9uay1pZnJhbWUtY29udGFpbmVyJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0xtRmtYMTl0WVdsdScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnVzJOc1lYTnpLajBpUjI5dloyeGxRV1J6SWwwPScpLFxuICAgICAgICAgICAgJyNoaXJkZXRlc2VrX2JveCcsXG4gICAgICAgIF0sXG4gICAgICAgIGlEb250Q2FyZUFib3V0Q29va2llczogW1xuICAgICAgICAgICAgJy5hbGVydC1pbmZvW2RhdGEtYmxvY2stdHJhY2sqPVwiQ29va2llTm90aWNlXCJdJyxcbiAgICAgICAgICAgICcuTW9kdWxlVGVtcGxhdGVDb29raWVJbmRpY2F0b3InLFxuICAgICAgICAgICAgJy5vLS1jb29raWVzLS1jb250YWluZXInLFxuICAgICAgICAgICAgJyNjb29raWVzLXBvbGljeS1zdGlja3knLFxuICAgICAgICAgICAgJyNzdGlja3lDb29raWVCYXInLFxuICAgICAgICBdLFxuICAgICAgICBpY2VsYW5kaWNBYnA6IFtmcm9tQjY0KCdRVnRvY21WbVhqMGlMMlp5WVcxbGQyOXlheTl5WlhOdmRYSmpaWE12Wm05eWJYTXZZV1J6TG1GemNIZ2lYUT09JyldLFxuICAgICAgICBsYXR2aWFuOiBbXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVBTSm9kSFJ3T2k4dmQzZDNMbk5oYkdsa2VtbHVhUzVzZGk4aVhWdHpkSGxzWlQwaVpHbHpjR3hoZVRvZ1lteHZZMnM3SUhkcFpIUm9PaUF4TWpCd2VEc2dhR1ZwWjJoME8nICtcbiAgICAgICAgICAgICAgICAnaUEwTUhCNE95QnZkbVZ5Wm14dmR6b2dhR2xrWkdWdU95QndiM05wZEdsdmJqb2djbVZzWVhScGRtVTdJbDA9JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVBTSm9kSFJ3T2k4dmQzZDNMbk5oYkdsa2VtbHVhUzVzZGk4aVhWdHpkSGxzWlQwaVpHbHpjR3hoZVRvZ1lteHZZMnM3SUhkcFpIUm9PaUE0T0hCNE95Qm9aV2xuYUhRNkknICtcbiAgICAgICAgICAgICAgICAnRE14Y0hnN0lHOTJaWEptYkc5M09pQm9hV1JrWlc0N0lIQnZjMmwwYVc5dU9pQnlaV3hoZEdsMlpUc2lYUT09JyksXG4gICAgICAgIF0sXG4gICAgICAgIGxpc3RLcjogW1xuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpTHk5aFpDNXdiR0Z1WW5Cc2RYTXVZMjh1YTNJdklsMD0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kyeHBkbVZ5WlVGa1YzSmhjSEJsY2c9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpTHk5aFpIWXVhVzFoWkhKbGNDNWpieTVyY2k4aVhRPT0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ2FXNXpMbVpoYzNSMmFXVjNMV0ZrJyksXG4gICAgICAgICAgICAnLnJldmVudWVfdW5pdF9pdGVtLmRhYmxlJyxcbiAgICAgICAgXSxcbiAgICAgICAgbGlzdGVBcjogW1xuICAgICAgICAgICAgZnJvbUI2NCgnTG1kbGJXbHVhVXhDTVVGaycpLFxuICAgICAgICAgICAgJy5yaWdodC1hbmQtbGVmdC1zcG9uc2VycycsXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbUtqMGlMbUZtYkdGdExtbHVabThpWFE9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpWW05dmNtRnhMbTl5WnlKZCcpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpWkhWaWFYcDZiR1V1WTI5dEwyRnlMejkxZEcxZmMyOTFjbU5sUFNKZCcpLFxuICAgICAgICBdLFxuICAgICAgICBsaXN0ZUZyOiBbXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0RvdkwzQnliMjF2TG5aaFpHOXlMbU52YlM4aVhRPT0nKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kyRmtZMjl1ZEdGcGJtVnlYM0psWTJobGNtTm9aUT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbUtqMGlkMlZpYjNKaGJXRXVabkl2Wm1ObmFTMWlhVzR2SWwwPScpLFxuICAgICAgICAgICAgJy5zaXRlLXB1Yi1pbnRlcnN0aXRpZWwnLFxuICAgICAgICAgICAgJ2RpdltpZF49XCJjcnQtXCJdW2RhdGEtY3JpdGVvLWlkXScsXG4gICAgICAgIF0sXG4gICAgICAgIG9mZmljaWFsUG9saXNoOiBbXG4gICAgICAgICAgICAnI2NlbmVvLXBsYWNlaG9sZGVyLWNlbmVvLTEyJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ1cyaHlaV1plUFNKb2RIUndjem92TDJGbVppNXpaVzVrYUhWaUxuQnNMeUpkJyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbVhqMGlhSFIwY0RvdkwyRmtkbTFoYm1GblpYSXVkR1ZqYUdaMWJpNXdiQzl5WldScGNtVmpkQzhpWFE9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNEb3ZMM2QzZHk1MGNtbDZaWEl1Y0d3dlAzVjBiVjl6YjNWeVkyVWlYUT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdaR2wySTNOcllYQnBaV05mWVdRPScpLFxuICAgICAgICBdLFxuICAgICAgICBybzogW1xuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpTHk5aFptWjBjbXN1WVd4MFpYZ3VjbTh2UTI5MWJuUmxjaTlEYkdsamF5SmQnKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtWGowaWFIUjBjSE02THk5aWJHRmphMlp5YVdSaGVYTmhiR1Z6TG5KdkwzUnlheTl6YUc5d0x5SmQnKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtWGowaWFIUjBjSE02THk5bGRtVnVkQzR5Y0dWeVptOXliV0Z1ZEM1amIyMHZaWFpsYm5SekwyTnNhV05ySWwwPScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1YajBpYUhSMGNITTZMeTlzTG5CeWIyWnBkSE5vWVhKbExuSnZMeUpkJyksXG4gICAgICAgICAgICAnYVtocmVmXj1cIi91cmwvXCJdJyxcbiAgICAgICAgXSxcbiAgICAgICAgcnVBZDogW1xuICAgICAgICAgICAgZnJvbUI2NCgnWVZ0b2NtVm1LajBpTHk5bVpXSnlZWEpsTG5KMUx5SmQnKSxcbiAgICAgICAgICAgIGZyb21CNjQoJ1lWdG9jbVZtS2owaUx5OTFkR2x0Wnk1eWRTOGlYUT09JyksXG4gICAgICAgICAgICBmcm9tQjY0KCdZVnRvY21WbUtqMGlPaTh2WTJocGEybGthV3RwTG5KMUlsMD0nKSxcbiAgICAgICAgICAgICcjcGdlbGRpeicsXG4gICAgICAgICAgICAnLnlhbmRleC1ydGItYmxvY2snLFxuICAgICAgICBdLFxuICAgICAgICB0aGFpQWRzOiBbXG4gICAgICAgICAgICAnYVtocmVmKj1tYWNhdS11dGEtcG9wdXBdJyxcbiAgICAgICAgICAgIGZyb21CNjQoJ0kyRmtjeTFuYjI5bmJHVXRiV2xrWkd4bFgzSmxZM1JoYm1kc1pTMW5jbTkxY0E9PScpLFxuICAgICAgICAgICAgZnJvbUI2NCgnTG1Ga2N6TXdNSE09JyksXG4gICAgICAgICAgICAnLmJ1bXEnLFxuICAgICAgICAgICAgJy5pbWcta29zYW5hJyxcbiAgICAgICAgXSxcbiAgICAgICAgd2ViQW5ub3lhbmNlc1VsdHJhbGlzdDogW1xuICAgICAgICAgICAgJyNtb2Qtc29jaWFsLXNoYXJlLTInLFxuICAgICAgICAgICAgJyNzb2NpYWwtdG9vbHMnLFxuICAgICAgICAgICAgZnJvbUI2NCgnTG1OMGNHd3RablZzYkdKaGJtNWxjZz09JyksXG4gICAgICAgICAgICAnLnplcmduZXQtcmVjb21tZW5kJyxcbiAgICAgICAgICAgICcueXQuYnRuLWxpbmsuYnRuLW1kLmJ0bicsXG4gICAgICAgIF0sXG4gICAgfTtcbn1cbi8qKlxuICogVGhlIG9yZGVyIG9mIHRoZSByZXR1cm5lZCBhcnJheSBtZWFucyBub3RoaW5nIChpdCdzIGFsd2F5cyBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkpLlxuICpcbiAqIE5vdGljZSB0aGF0IHRoZSBzb3VyY2UgaXMgc2xpZ2h0bHkgdW5zdGFibGUuXG4gKiBTYWZhcmkgcHJvdmlkZXMgYSAyLXRhcHMgd2F5IHRvIGRpc2FibGUgYWxsIGNvbnRlbnQgYmxvY2tlcnMgb24gYSBwYWdlIHRlbXBvcmFyaWx5LlxuICogQWxzbyBjb250ZW50IGJsb2NrZXJzIGNhbiBiZSBkaXNhYmxlZCBwZXJtYW5lbnRseSBmb3IgYSBkb21haW4sIGJ1dCBpdCByZXF1aXJlcyA0IHRhcHMuXG4gKiBTbyBlbXB0eSBhcnJheSBzaG91bGRuJ3QgYmUgdHJlYXRlZCBhcyBcIm5vIGJsb2NrZXJzXCIsIGl0IHNob3VsZCBiZSB0cmVhdGVkIGFzIFwibm8gc2lnbmFsXCIuXG4gKiBJZiB5b3UgYXJlIGEgd2Vic2l0ZSBvd25lciwgZG9uJ3QgbWFrZSB5b3VyIHZpc2l0b3JzIHdhbnQgdG8gZGlzYWJsZSBjb250ZW50IGJsb2NrZXJzLlxuICovXG5hc3luYyBmdW5jdGlvbiBnZXREb21CbG9ja2Vycyh7IGRlYnVnIH0gPSB7fSkge1xuICAgIGlmICghaXNBcHBsaWNhYmxlKCkpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgY29uc3QgZmlsdGVycyA9IGdldEZpbHRlcnMoKTtcbiAgICBjb25zdCBmaWx0ZXJOYW1lcyA9IE9iamVjdC5rZXlzKGZpbHRlcnMpO1xuICAgIGNvbnN0IGFsbFNlbGVjdG9ycyA9IFtdLmNvbmNhdCguLi5maWx0ZXJOYW1lcy5tYXAoKGZpbHRlck5hbWUpID0+IGZpbHRlcnNbZmlsdGVyTmFtZV0pKTtcbiAgICBjb25zdCBibG9ja2VkU2VsZWN0b3JzID0gYXdhaXQgZ2V0QmxvY2tlZFNlbGVjdG9ycyhhbGxTZWxlY3RvcnMpO1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgICBwcmludERlYnVnKGZpbHRlcnMsIGJsb2NrZWRTZWxlY3RvcnMpO1xuICAgIH1cbiAgICBjb25zdCBhY3RpdmVCbG9ja2VycyA9IGZpbHRlck5hbWVzLmZpbHRlcigoZmlsdGVyTmFtZSkgPT4ge1xuICAgICAgICBjb25zdCBzZWxlY3RvcnMgPSBmaWx0ZXJzW2ZpbHRlck5hbWVdO1xuICAgICAgICBjb25zdCBibG9ja2VkQ291bnQgPSBjb3VudFRydXRoeShzZWxlY3RvcnMubWFwKChzZWxlY3RvcikgPT4gYmxvY2tlZFNlbGVjdG9yc1tzZWxlY3Rvcl0pKTtcbiAgICAgICAgcmV0dXJuIGJsb2NrZWRDb3VudCA+IHNlbGVjdG9ycy5sZW5ndGggKiAwLjY7XG4gICAgfSk7XG4gICAgYWN0aXZlQmxvY2tlcnMuc29ydCgpO1xuICAgIHJldHVybiBhY3RpdmVCbG9ja2Vycztcbn1cbmZ1bmN0aW9uIGlzQXBwbGljYWJsZSgpIHtcbiAgICAvLyBTYWZhcmkgKGRlc2t0b3AgYW5kIG1vYmlsZSkgYW5kIGFsbCBBbmRyb2lkIGJyb3dzZXJzIGtlZXAgY29udGVudCBibG9ja2VycyBpbiBib3RoIHJlZ3VsYXIgYW5kIHByaXZhdGUgbW9kZVxuICAgIHJldHVybiBpc1dlYktpdCgpIHx8IGlzQW5kcm9pZCgpO1xufVxuYXN5bmMgZnVuY3Rpb24gZ2V0QmxvY2tlZFNlbGVjdG9ycyhzZWxlY3RvcnMpIHtcbiAgICB2YXIgX2E7XG4gICAgY29uc3QgZCA9IGRvY3VtZW50O1xuICAgIGNvbnN0IHJvb3QgPSBkLmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnN0IGVsZW1lbnRzID0gbmV3IEFycmF5KHNlbGVjdG9ycy5sZW5ndGgpO1xuICAgIGNvbnN0IGJsb2NrZWRTZWxlY3RvcnMgPSB7fTsgLy8gU2V0KCkgaXNuJ3QgdXNlZCBqdXN0IGluIGNhc2Ugc29tZWJvZHkgbmVlZCBvbGRlciBicm93c2VyIHN1cHBvcnRcbiAgICBmb3JjZVNob3cocm9vdCk7XG4gICAgLy8gRmlyc3QgY3JlYXRlIGFsbCBlbGVtZW50cyB0aGF0IGNhbiBiZSBibG9ja2VkLiBJZiB0aGUgRE9NIHN0ZXBzIGJlbG93IGFyZSBkb25lIGluIGEgc2luZ2xlIGN5Y2xlLFxuICAgIC8vIGJyb3dzZXIgd2lsbCBhbHRlcm5hdGUgdHJlZSBtb2RpZmljYXRpb24gYW5kIGxheW91dCByZWFkaW5nLCB0aGF0IGlzIHZlcnkgc2xvdy5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdG9ycy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gc2VsZWN0b3JUb0VsZW1lbnQoc2VsZWN0b3JzW2ldKTtcbiAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZSA9PT0gJ0RJQUxPRycpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc2hvdygpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhvbGRlciA9IGQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7IC8vIFByb3RlY3RzIGZyb20gdW53YW50ZWQgZWZmZWN0cyBvZiBgK2AgYW5kIGB+YCBzZWxlY3RvcnMgb2YgZmlsdGVyc1xuICAgICAgICBmb3JjZVNob3coaG9sZGVyKTtcbiAgICAgICAgaG9sZGVyLmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICByb290LmFwcGVuZENoaWxkKGhvbGRlcik7XG4gICAgICAgIGVsZW1lbnRzW2ldID0gZWxlbWVudDtcbiAgICB9XG4gICAgLy8gZG9jdW1lbnQuYm9keSBjYW4gYmUgbnVsbCB3aGlsZSB0aGUgcGFnZSBpcyBsb2FkaW5nXG4gICAgd2hpbGUgKCFkLmJvZHkpIHtcbiAgICAgICAgYXdhaXQgd2FpdCg1MCk7XG4gICAgfVxuICAgIGQuYm9keS5hcHBlbmRDaGlsZChyb290KTtcbiAgICB0cnkge1xuICAgICAgICAvLyBUaGVuIGNoZWNrIHdoaWNoIG9mIHRoZSBlbGVtZW50cyBhcmUgYmxvY2tlZFxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdG9ycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKCFlbGVtZW50c1tpXS5vZmZzZXRQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBibG9ja2VkU2VsZWN0b3JzW3NlbGVjdG9yc1tpXV0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICAvLyBUaGVuIHJlbW92ZSB0aGUgZWxlbWVudHNcbiAgICAgICAgKF9hID0gcm9vdC5wYXJlbnROb2RlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EucmVtb3ZlQ2hpbGQocm9vdCk7XG4gICAgfVxuICAgIHJldHVybiBibG9ja2VkU2VsZWN0b3JzO1xufVxuZnVuY3Rpb24gZm9yY2VTaG93KGVsZW1lbnQpIHtcbiAgICBlbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCd2aXNpYmlsaXR5JywgJ2hpZGRlbicsICdpbXBvcnRhbnQnKTtcbiAgICBlbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCdkaXNwbGF5JywgJ2Jsb2NrJywgJ2ltcG9ydGFudCcpO1xufVxuZnVuY3Rpb24gcHJpbnREZWJ1ZyhmaWx0ZXJzLCBibG9ja2VkU2VsZWN0b3JzKSB7XG4gICAgbGV0IG1lc3NhZ2UgPSAnRE9NIGJsb2NrZXJzIGRlYnVnOlxcbmBgYCc7XG4gICAgZm9yIChjb25zdCBmaWx0ZXJOYW1lIG9mIE9iamVjdC5rZXlzKGZpbHRlcnMpKSB7XG4gICAgICAgIG1lc3NhZ2UgKz0gYFxcbiR7ZmlsdGVyTmFtZX06YDtcbiAgICAgICAgZm9yIChjb25zdCBzZWxlY3RvciBvZiBmaWx0ZXJzW2ZpbHRlck5hbWVdKSB7XG4gICAgICAgICAgICBtZXNzYWdlICs9IGBcXG4gICR7YmxvY2tlZFNlbGVjdG9yc1tzZWxlY3Rvcl0gPyAnXHVEODNEXHVERUFCJyA6ICdcdTI3QTFcdUZFMEYnfSAke3NlbGVjdG9yfWA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gY29uc29sZS5sb2cgaXMgb2sgaGVyZSBiZWNhdXNlIGl0J3MgdW5kZXIgYSBkZWJ1ZyBjbGF1c2VcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUubG9nKGAke21lc3NhZ2V9XFxuXFxgXFxgXFxgYCk7XG59XG5cbi8qKlxuICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9DU1MvQG1lZGlhL2NvbG9yLWdhbXV0XG4gKi9cbmZ1bmN0aW9uIGdldENvbG9yR2FtdXQoKSB7XG4gICAgLy8gcmVjMjAyMCBpbmNsdWRlcyBwMyBhbmQgcDMgaW5jbHVkZXMgc3JnYlxuICAgIGZvciAoY29uc3QgZ2FtdXQgb2YgWydyZWMyMDIwJywgJ3AzJywgJ3NyZ2InXSkge1xuICAgICAgICBpZiAobWF0Y2hNZWRpYShgKGNvbG9yLWdhbXV0OiAke2dhbXV0fSlgKS5tYXRjaGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2FtdXQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0NTUy9AbWVkaWEvaW52ZXJ0ZWQtY29sb3JzXG4gKi9cbmZ1bmN0aW9uIGFyZUNvbG9yc0ludmVydGVkKCkge1xuICAgIGlmIChkb2VzTWF0Y2gkNSgnaW52ZXJ0ZWQnKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGRvZXNNYXRjaCQ1KCdub25lJykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuZnVuY3Rpb24gZG9lc01hdGNoJDUodmFsdWUpIHtcbiAgICByZXR1cm4gbWF0Y2hNZWRpYShgKGludmVydGVkLWNvbG9yczogJHt2YWx1ZX0pYCkubWF0Y2hlcztcbn1cblxuLyoqXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0NTUy9AbWVkaWEvZm9yY2VkLWNvbG9yc1xuICovXG5mdW5jdGlvbiBhcmVDb2xvcnNGb3JjZWQoKSB7XG4gICAgaWYgKGRvZXNNYXRjaCQ0KCdhY3RpdmUnKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKGRvZXNNYXRjaCQ0KCdub25lJykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuZnVuY3Rpb24gZG9lc01hdGNoJDQodmFsdWUpIHtcbiAgICByZXR1cm4gbWF0Y2hNZWRpYShgKGZvcmNlZC1jb2xvcnM6ICR7dmFsdWV9KWApLm1hdGNoZXM7XG59XG5cbmNvbnN0IG1heFZhbHVlVG9DaGVjayA9IDEwMDtcbi8qKlxuICogSWYgdGhlIGRpc3BsYXkgaXMgbW9ub2Nocm9tZSAoZS5nLiBibGFjayZ3aGl0ZSksIHRoZSB2YWx1ZSB3aWxsIGJlIFx1MjI2NTAgYW5kIHdpbGwgbWVhbiB0aGUgbnVtYmVyIG9mIGJpdHMgcGVyIHBpeGVsLlxuICogSWYgdGhlIGRpc3BsYXkgaXMgbm90IG1vbm9jaHJvbWUsIHRoZSByZXR1cm5lZCB2YWx1ZSB3aWxsIGJlIDAuXG4gKiBJZiB0aGUgYnJvd3NlciBkb2Vzbid0IHN1cHBvcnQgdGhpcyBmZWF0dXJlLCB0aGUgcmV0dXJuZWQgdmFsdWUgd2lsbCBiZSB1bmRlZmluZWQuXG4gKlxuICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9DU1MvQG1lZGlhL21vbm9jaHJvbWVcbiAqL1xuZnVuY3Rpb24gZ2V0TW9ub2Nocm9tZURlcHRoKCkge1xuICAgIGlmICghbWF0Y2hNZWRpYSgnKG1pbi1tb25vY2hyb21lOiAwKScpLm1hdGNoZXMpIHtcbiAgICAgICAgLy8gVGhlIG1lZGlhIGZlYXR1cmUgaXNuJ3Qgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIEEgdmFyaWF0aW9uIG9mIGJpbmFyeSBzZWFyY2ggYWxnb3JpdGhtIGNhbiBiZSB1c2VkIGhlcmUuXG4gICAgLy8gQnV0IHNpbmNlIGV4cGVjdGVkIHZhbHVlcyBhcmUgdmVyeSBzbWFsbCAoXHUyMjY0MTApLCB0aGVyZSBpcyBubyBzZW5zZSBpbiBhZGRpbmcgdGhlIGNvbXBsZXhpdHkuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gbWF4VmFsdWVUb0NoZWNrOyArK2kpIHtcbiAgICAgICAgaWYgKG1hdGNoTWVkaWEoYChtYXgtbW9ub2Nocm9tZTogJHtpfSlgKS5tYXRjaGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RvbyBoaWdoIHZhbHVlJyk7XG59XG5cbi8qKlxuICogQHNlZSBodHRwczovL3d3dy53My5vcmcvVFIvbWVkaWFxdWVyaWVzLTUvI3ByZWZlcnMtY29udHJhc3RcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0BtZWRpYS9wcmVmZXJzLWNvbnRyYXN0XG4gKi9cbmZ1bmN0aW9uIGdldENvbnRyYXN0UHJlZmVyZW5jZSgpIHtcbiAgICBpZiAoZG9lc01hdGNoJDMoJ25vLXByZWZlcmVuY2UnKSkge1xuICAgICAgICByZXR1cm4gMCAvKiBDb250cmFzdFByZWZlcmVuY2UuTm9uZSAqLztcbiAgICB9XG4gICAgLy8gVGhlIHNvdXJjZXMgY29udHJhZGljdCBvbiB0aGUga2V5d29yZHMuIFByb2JhYmx5ICdoaWdoJyBhbmQgJ2xvdycgd2lsbCBuZXZlciBiZSBpbXBsZW1lbnRlZC5cbiAgICAvLyBOZWVkIHRvIGNoZWNrIGl0IHdoZW4gYWxsIGJyb3dzZXJzIGltcGxlbWVudCB0aGUgZmVhdHVyZS5cbiAgICBpZiAoZG9lc01hdGNoJDMoJ2hpZ2gnKSB8fCBkb2VzTWF0Y2gkMygnbW9yZScpKSB7XG4gICAgICAgIHJldHVybiAxIC8qIENvbnRyYXN0UHJlZmVyZW5jZS5Nb3JlICovO1xuICAgIH1cbiAgICBpZiAoZG9lc01hdGNoJDMoJ2xvdycpIHx8IGRvZXNNYXRjaCQzKCdsZXNzJykpIHtcbiAgICAgICAgcmV0dXJuIC0xIC8qIENvbnRyYXN0UHJlZmVyZW5jZS5MZXNzICovO1xuICAgIH1cbiAgICBpZiAoZG9lc01hdGNoJDMoJ2ZvcmNlZCcpKSB7XG4gICAgICAgIHJldHVybiAxMCAvKiBDb250cmFzdFByZWZlcmVuY2UuRm9yY2VkQ29sb3JzICovO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuZnVuY3Rpb24gZG9lc01hdGNoJDModmFsdWUpIHtcbiAgICByZXR1cm4gbWF0Y2hNZWRpYShgKHByZWZlcnMtY29udHJhc3Q6ICR7dmFsdWV9KWApLm1hdGNoZXM7XG59XG5cbi8qKlxuICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9DU1MvQG1lZGlhL3ByZWZlcnMtcmVkdWNlZC1tb3Rpb25cbiAqL1xuZnVuY3Rpb24gaXNNb3Rpb25SZWR1Y2VkKCkge1xuICAgIGlmIChkb2VzTWF0Y2gkMigncmVkdWNlJykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChkb2VzTWF0Y2gkMignbm8tcHJlZmVyZW5jZScpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cbmZ1bmN0aW9uIGRvZXNNYXRjaCQyKHZhbHVlKSB7XG4gICAgcmV0dXJuIG1hdGNoTWVkaWEoYChwcmVmZXJzLXJlZHVjZWQtbW90aW9uOiAke3ZhbHVlfSlgKS5tYXRjaGVzO1xufVxuXG4vKipcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0BtZWRpYS9wcmVmZXJzLXJlZHVjZWQtdHJhbnNwYXJlbmN5XG4gKi9cbmZ1bmN0aW9uIGlzVHJhbnNwYXJlbmN5UmVkdWNlZCgpIHtcbiAgICBpZiAoZG9lc01hdGNoJDEoJ3JlZHVjZScpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoZG9lc01hdGNoJDEoJ25vLXByZWZlcmVuY2UnKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG59XG5mdW5jdGlvbiBkb2VzTWF0Y2gkMSh2YWx1ZSkge1xuICAgIHJldHVybiBtYXRjaE1lZGlhKGAocHJlZmVycy1yZWR1Y2VkLXRyYW5zcGFyZW5jeTogJHt2YWx1ZX0pYCkubWF0Y2hlcztcbn1cblxuLyoqXG4gKiBAc2VlIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9tZWRpYXF1ZXJpZXMtNS8jZHluYW1pYy1yYW5nZVxuICovXG5mdW5jdGlvbiBpc0hEUigpIHtcbiAgICBpZiAoZG9lc01hdGNoKCdoaWdoJykpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChkb2VzTWF0Y2goJ3N0YW5kYXJkJykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuZnVuY3Rpb24gZG9lc01hdGNoKHZhbHVlKSB7XG4gICAgcmV0dXJuIG1hdGNoTWVkaWEoYChkeW5hbWljLXJhbmdlOiAke3ZhbHVlfSlgKS5tYXRjaGVzO1xufVxuXG5jb25zdCBNID0gTWF0aDsgLy8gVG8gcmVkdWNlIHRoZSBtaW5pZmllZCBjb2RlIHNpemVcbmNvbnN0IGZhbGxiYWNrRm4gPSAoKSA9PiAwO1xuLyoqXG4gKiBAc2VlIGh0dHBzOi8vZ2l0bGFiLnRvcnByb2plY3Qub3JnL2xlZ2FjeS90cmFjLy0vaXNzdWVzLzEzMDE4XG4gKiBAc2VlIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTUzMTkxNVxuICovXG5mdW5jdGlvbiBnZXRNYXRoRmluZ2VycHJpbnQoKSB7XG4gICAgLy8gTmF0aXZlIG9wZXJhdGlvbnNcbiAgICBjb25zdCBhY29zID0gTS5hY29zIHx8IGZhbGxiYWNrRm47XG4gICAgY29uc3QgYWNvc2ggPSBNLmFjb3NoIHx8IGZhbGxiYWNrRm47XG4gICAgY29uc3QgYXNpbiA9IE0uYXNpbiB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IGFzaW5oID0gTS5hc2luaCB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IGF0YW5oID0gTS5hdGFuaCB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IGF0YW4gPSBNLmF0YW4gfHwgZmFsbGJhY2tGbjtcbiAgICBjb25zdCBzaW4gPSBNLnNpbiB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IHNpbmggPSBNLnNpbmggfHwgZmFsbGJhY2tGbjtcbiAgICBjb25zdCBjb3MgPSBNLmNvcyB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IGNvc2ggPSBNLmNvc2ggfHwgZmFsbGJhY2tGbjtcbiAgICBjb25zdCB0YW4gPSBNLnRhbiB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IHRhbmggPSBNLnRhbmggfHwgZmFsbGJhY2tGbjtcbiAgICBjb25zdCBleHAgPSBNLmV4cCB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IGV4cG0xID0gTS5leHBtMSB8fCBmYWxsYmFja0ZuO1xuICAgIGNvbnN0IGxvZzFwID0gTS5sb2cxcCB8fCBmYWxsYmFja0ZuO1xuICAgIC8vIE9wZXJhdGlvbiBwb2x5ZmlsbHNcbiAgICBjb25zdCBwb3dQSSA9ICh2YWx1ZSkgPT4gTS5wb3coTS5QSSwgdmFsdWUpO1xuICAgIGNvbnN0IGFjb3NoUGYgPSAodmFsdWUpID0+IE0ubG9nKHZhbHVlICsgTS5zcXJ0KHZhbHVlICogdmFsdWUgLSAxKSk7XG4gICAgY29uc3QgYXNpbmhQZiA9ICh2YWx1ZSkgPT4gTS5sb2codmFsdWUgKyBNLnNxcnQodmFsdWUgKiB2YWx1ZSArIDEpKTtcbiAgICBjb25zdCBhdGFuaFBmID0gKHZhbHVlKSA9PiBNLmxvZygoMSArIHZhbHVlKSAvICgxIC0gdmFsdWUpKSAvIDI7XG4gICAgY29uc3Qgc2luaFBmID0gKHZhbHVlKSA9PiBNLmV4cCh2YWx1ZSkgLSAxIC8gTS5leHAodmFsdWUpIC8gMjtcbiAgICBjb25zdCBjb3NoUGYgPSAodmFsdWUpID0+IChNLmV4cCh2YWx1ZSkgKyAxIC8gTS5leHAodmFsdWUpKSAvIDI7XG4gICAgY29uc3QgZXhwbTFQZiA9ICh2YWx1ZSkgPT4gTS5leHAodmFsdWUpIC0gMTtcbiAgICBjb25zdCB0YW5oUGYgPSAodmFsdWUpID0+IChNLmV4cCgyICogdmFsdWUpIC0gMSkgLyAoTS5leHAoMiAqIHZhbHVlKSArIDEpO1xuICAgIGNvbnN0IGxvZzFwUGYgPSAodmFsdWUpID0+IE0ubG9nKDEgKyB2YWx1ZSk7XG4gICAgLy8gTm90ZTogY29uc3RhbnQgdmFsdWVzIGFyZSBlbXBpcmljYWxcbiAgICByZXR1cm4ge1xuICAgICAgICBhY29zOiBhY29zKDAuMTIzMTI0MjM0MjM0MjM0MjQyKSxcbiAgICAgICAgYWNvc2g6IGFjb3NoKDFlMzA4KSxcbiAgICAgICAgYWNvc2hQZjogYWNvc2hQZigxZTE1NCksXG4gICAgICAgIGFzaW46IGFzaW4oMC4xMjMxMjQyMzQyMzQyMzQyNDIpLFxuICAgICAgICBhc2luaDogYXNpbmgoMSksXG4gICAgICAgIGFzaW5oUGY6IGFzaW5oUGYoMSksXG4gICAgICAgIGF0YW5oOiBhdGFuaCgwLjUpLFxuICAgICAgICBhdGFuaFBmOiBhdGFuaFBmKDAuNSksXG4gICAgICAgIGF0YW46IGF0YW4oMC41KSxcbiAgICAgICAgc2luOiBzaW4oLTFlMzAwKSxcbiAgICAgICAgc2luaDogc2luaCgxKSxcbiAgICAgICAgc2luaFBmOiBzaW5oUGYoMSksXG4gICAgICAgIGNvczogY29zKDEwLjAwMDAwMDAwMDEyMyksXG4gICAgICAgIGNvc2g6IGNvc2goMSksXG4gICAgICAgIGNvc2hQZjogY29zaFBmKDEpLFxuICAgICAgICB0YW46IHRhbigtMWUzMDApLFxuICAgICAgICB0YW5oOiB0YW5oKDEpLFxuICAgICAgICB0YW5oUGY6IHRhbmhQZigxKSxcbiAgICAgICAgZXhwOiBleHAoMSksXG4gICAgICAgIGV4cG0xOiBleHBtMSgxKSxcbiAgICAgICAgZXhwbTFQZjogZXhwbTFQZigxKSxcbiAgICAgICAgbG9nMXA6IGxvZzFwKDEwKSxcbiAgICAgICAgbG9nMXBQZjogbG9nMXBQZigxMCksXG4gICAgICAgIHBvd1BJOiBwb3dQSSgtMTAwKSxcbiAgICB9O1xufVxuXG4vKipcbiAqIFdlIHVzZSBtIG9yIHcgYmVjYXVzZSB0aGVzZSB0d28gY2hhcmFjdGVycyB0YWtlIHVwIHRoZSBtYXhpbXVtIHdpZHRoLlxuICogQWxzbyB0aGVyZSBhcmUgYSBjb3VwbGUgb2YgbGlnYXR1cmVzLlxuICovXG5jb25zdCBkZWZhdWx0VGV4dCA9ICdtbU13V0xsaUkwZmlmbE8mMSc7XG4vKipcbiAqIFNldHRpbmdzIG9mIHRleHQgYmxvY2tzIHRvIG1lYXN1cmUuIFRoZSBrZXlzIGFyZSByYW5kb20gYnV0IHBlcnNpc3RlbnQgd29yZHMuXG4gKi9cbmNvbnN0IHByZXNldHMgPSB7XG4gICAgLyoqXG4gICAgICogVGhlIGRlZmF1bHQgZm9udC4gVXNlciBjYW4gY2hhbmdlIGl0IGluIGRlc2t0b3AgQ2hyb21lLCBkZXNrdG9wIEZpcmVmb3gsIElFIDExLFxuICAgICAqIEFuZHJvaWQgQ2hyb21lIChidXQgb25seSB3aGVuIHRoZSBzaXplIGlzIFx1MjI2NSB0aGFuIHRoZSBkZWZhdWx0KSBhbmQgQW5kcm9pZCBGaXJlZm94LlxuICAgICAqL1xuICAgIGRlZmF1bHQ6IFtdLFxuICAgIC8qKiBPUyBmb250IG9uIG1hY09TLiBVc2VyIGNhbiBjaGFuZ2UgaXRzIHNpemUgYW5kIHdlaWdodC4gQXBwbGllcyBhZnRlciBTYWZhcmkgcmVzdGFydC4gKi9cbiAgICBhcHBsZTogW3sgZm9udDogJy1hcHBsZS1zeXN0ZW0tYm9keScgfV0sXG4gICAgLyoqIFVzZXIgY2FuIGNoYW5nZSBpdCBpbiBkZXNrdG9wIENocm9tZSBhbmQgZGVza3RvcCBGaXJlZm94LiAqL1xuICAgIHNlcmlmOiBbeyBmb250RmFtaWx5OiAnc2VyaWYnIH1dLFxuICAgIC8qKiBVc2VyIGNhbiBjaGFuZ2UgaXQgaW4gZGVza3RvcCBDaHJvbWUgYW5kIGRlc2t0b3AgRmlyZWZveC4gKi9cbiAgICBzYW5zOiBbeyBmb250RmFtaWx5OiAnc2Fucy1zZXJpZicgfV0sXG4gICAgLyoqIFVzZXIgY2FuIGNoYW5nZSBpdCBpbiBkZXNrdG9wIENocm9tZSBhbmQgZGVza3RvcCBGaXJlZm94LiAqL1xuICAgIG1vbm86IFt7IGZvbnRGYW1pbHk6ICdtb25vc3BhY2UnIH1dLFxuICAgIC8qKlxuICAgICAqIENoZWNrIHRoZSBzbWFsbGVzdCBhbGxvd2VkIGZvbnQgc2l6ZS4gVXNlciBjYW4gY2hhbmdlIGl0IGluIGRlc2t0b3AgQ2hyb21lLCBkZXNrdG9wIEZpcmVmb3ggYW5kIGRlc2t0b3AgU2FmYXJpLlxuICAgICAqIFRoZSBoZWlnaHQgY2FuIGJlIDAgaW4gQ2hyb21lIG9uIGEgcmV0aW5hIGRpc3BsYXkuXG4gICAgICovXG4gICAgbWluOiBbeyBmb250U2l6ZTogJzFweCcgfV0sXG4gICAgLyoqIFRlbGxzIG9uZSBPUyBmcm9tIGFub3RoZXIgaW4gZGVza3RvcCBDaHJvbWUuICovXG4gICAgc3lzdGVtOiBbeyBmb250RmFtaWx5OiAnc3lzdGVtLXVpJyB9XSxcbn07XG4vKipcbiAqIFRoZSByZXN1bHQgaXMgYSBkaWN0aW9uYXJ5IG9mIHRoZSB3aWR0aCBvZiB0aGUgdGV4dCBzYW1wbGVzLlxuICogSGVpZ2h0cyBhcmVuJ3QgaW5jbHVkZWQgYmVjYXVzZSB0aGV5IGdpdmUgbm8gZXh0cmEgZW50cm9weSBhbmQgYXJlIHVuc3RhYmxlLlxuICpcbiAqIFRoZSByZXN1bHQgaXMgdmVyeSBzdGFibGUgaW4gSUUgMTEsIEVkZ2UgMTggYW5kIFNhZmFyaSAxNC5cbiAqIFRoZSByZXN1bHQgY2hhbmdlcyB3aGVuIHRoZSBPUyBwaXhlbCBkZW5zaXR5IGNoYW5nZXMgaW4gQ2hyb21pdW0gODcuIFRoZSByZWFsIHBpeGVsIGRlbnNpdHkgaXMgcmVxdWlyZWQgdG8gc29sdmUsXG4gKiBidXQgc2VlbXMgbGlrZSBpdCdzIGltcG9zc2libGU6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xNzEzNzcxLzExMTg3MDkuXG4gKiBUaGUgXCJtaW5cIiBhbmQgdGhlIFwibW9ub1wiIChvbmx5IG9uIFdpbmRvd3MpIHZhbHVlIG1heSBjaGFuZ2Ugd2hlbiB0aGUgcGFnZSBpcyB6b29tZWQgaW4gRmlyZWZveCA4Ny5cbiAqL1xuZnVuY3Rpb24gZ2V0Rm9udFByZWZlcmVuY2VzKCkge1xuICAgIHJldHVybiB3aXRoTmF0dXJhbEZvbnRzKChkb2N1bWVudCwgY29udGFpbmVyKSA9PiB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0ge307XG4gICAgICAgIGNvbnN0IHNpemVzID0ge307XG4gICAgICAgIC8vIEZpcnN0IGNyZWF0ZSBhbGwgZWxlbWVudHMgdG8gbWVhc3VyZS4gSWYgdGhlIERPTSBzdGVwcyBiZWxvdyBhcmUgZG9uZSBpbiBhIHNpbmdsZSBjeWNsZSxcbiAgICAgICAgLy8gYnJvd3NlciB3aWxsIGFsdGVybmF0ZSB0cmVlIG1vZGlmaWNhdGlvbiBhbmQgbGF5b3V0IHJlYWRpbmcsIHRoYXQgaXMgdmVyeSBzbG93LlxuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhwcmVzZXRzKSkge1xuICAgICAgICAgICAgY29uc3QgW3N0eWxlID0ge30sIHRleHQgPSBkZWZhdWx0VGV4dF0gPSBwcmVzZXRzW2tleV07XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgICAgICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9IHRleHQ7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlLndoaXRlU3BhY2UgPSAnbm93cmFwJztcbiAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhzdHlsZSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHN0eWxlW25hbWVdO1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbGVtZW50c1trZXldID0gZWxlbWVudDtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmQoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnInKSwgZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlbiBtZWFzdXJlIHRoZSBjcmVhdGVkIGVsZW1lbnRzXG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHByZXNldHMpKSB7XG4gICAgICAgICAgICBzaXplc1trZXldID0gZWxlbWVudHNba2V5XS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2l6ZXM7XG4gICAgfSk7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBET00gZW52aXJvbm1lbnQgdGhhdCBwcm92aWRlcyB0aGUgbW9zdCBuYXR1cmFsIGZvbnQgYXZhaWxhYmxlLCBpbmNsdWRpbmcgQW5kcm9pZCBPUyBmb250LlxuICogTWVhc3VyZW1lbnRzIG9mIHRoZSBlbGVtZW50cyBhcmUgem9vbS1pbmRlcGVuZGVudC5cbiAqIERvbid0IHB1dCBhIGNvbnRlbnQgdG8gbWVhc3VyZSBpbnNpZGUgYW4gYWJzb2x1dGVseSBwb3NpdGlvbmVkIGVsZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIHdpdGhOYXR1cmFsRm9udHMoYWN0aW9uLCBjb250YWluZXJXaWR0aFB4ID0gNDAwMCkge1xuICAgIC8qXG4gICAgICogUmVxdWlyZW1lbnRzIGZvciBBbmRyb2lkIENocm9tZSB0byBhcHBseSB0aGUgc3lzdGVtIGZvbnQgc2l6ZSB0byBhIHRleHQgaW5zaWRlIGFuIGlmcmFtZTpcbiAgICAgKiAtIFRoZSBpZnJhbWUgbXVzdG4ndCBoYXZlIGEgYGRpc3BsYXk6IG5vbmU7YCBzdHlsZTtcbiAgICAgKiAtIFRoZSB0ZXh0IG11c3RuJ3QgYmUgcG9zaXRpb25lZCBhYnNvbHV0ZWx5O1xuICAgICAqIC0gVGhlIHRleHQgYmxvY2sgbXVzdCBiZSB3aWRlIGVub3VnaC5cbiAgICAgKiAgIDI1NjBweCBvbiBzb21lIGRldmljZXMgaW4gcG9ydHJhaXQgb3JpZW50YXRpb24gZm9yIHRoZSBiaWdnZXN0IGZvbnQgc2l6ZSBvcHRpb24gKDMycHgpO1xuICAgICAqIC0gVGhlcmUgbXVzdCBiZSBtdWNoIGVub3VnaCB0ZXh0IHRvIGZvcm0gYSBmZXcgbGluZXMgKEkgZG9uJ3Qga25vdyB0aGUgZXhhY3QgbnVtYmVycyk7XG4gICAgICogLSBUaGUgdGV4dCBtdXN0IGhhdmUgdGhlIGB0ZXh0LXNpemUtYWRqdXN0OiBub25lYCBzdHlsZS4gT3RoZXJ3aXNlIHRoZSB0ZXh0IHdpbGwgc2NhbGUgaW4gXCJEZXNrdG9wIHNpdGVcIiBtb2RlO1xuICAgICAqXG4gICAgICogUmVxdWlyZW1lbnRzIGZvciBBbmRyb2lkIEZpcmVmb3ggdG8gYXBwbHkgdGhlIHN5c3RlbSBmb250IHNpemUgdG8gYSB0ZXh0IGluc2lkZSBhbiBpZnJhbWU6XG4gICAgICogLSBUaGUgaWZyYW1lIGRvY3VtZW50IG11c3QgaGF2ZSBhIGhlYWRlcjogYDxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MVwiIC8+YC5cbiAgICAgKiAgIFRoZSBvbmx5IHdheSB0byBzZXQgaXQgaXMgdG8gdXNlIHRoZSBgc3JjZG9jYCBhdHRyaWJ1dGUgb2YgdGhlIGlmcmFtZTtcbiAgICAgKiAtIFRoZSBpZnJhbWUgY29udGVudCBtdXN0IGdldCBsb2FkZWQgYmVmb3JlIGFkZGluZyBleHRyYSBjb250ZW50IHdpdGggSmF2YVNjcmlwdDtcbiAgICAgKlxuICAgICAqIGh0dHBzOi8vZXhhbXBsZS5jb20gYXMgdGhlIGlmcmFtZSB0YXJnZXQgYWx3YXlzIGluaGVyaXRzIEFuZHJvaWQgZm9udCBzZXR0aW5ncyBzbyBpdCBjYW4gYmUgdXNlZCBhcyBhIHJlZmVyZW5jZS5cbiAgICAgKlxuICAgICAqIE9ic2VydmF0aW9ucyBvbiBob3cgcGFnZSB6b29tIGFmZmVjdHMgdGhlIG1lYXN1cmVtZW50czpcbiAgICAgKiAtIG1hY09TIFNhZmFyaSAxMS4xLCAxMi4xLCAxMy4xLCAxNC4wOiB6b29tIHJlc2V0ICsgb2Zmc2V0V2lkdGggPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gbWFjT1MgU2FmYXJpIDExLjEsIDEyLjEsIDEzLjEsIDE0LjA6IHpvb20gcmVzZXQgKyBnZXRCb3VuZGluZ0NsaWVudFJlY3QgPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gbWFjT1MgU2FmYXJpIDE0LjA6IG9mZnNldFdpZHRoID0gNSUgZmx1Y3R1YXRpb247XG4gICAgICogLSBtYWNPUyBTYWZhcmkgMTQuMDogZ2V0Qm91bmRpbmdDbGllbnRSZWN0ID0gNSUgZmx1Y3R1YXRpb247XG4gICAgICogLSBpT1MgU2FmYXJpIDksIDEwLCAxMS4wLCAxMi4wOiBoYXZlbid0IGZvdW5kIGEgd2F5IHRvIHpvb20gYSBwYWdlIChwaW5jaCBkb2Vzbid0IGNoYW5nZSBsYXlvdXQpO1xuICAgICAqIC0gaU9TIFNhZmFyaSAxMy4xLCAxNC4wOiB6b29tIHJlc2V0ICsgb2Zmc2V0V2lkdGggPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gaU9TIFNhZmFyaSAxMy4xLCAxNC4wOiB6b29tIHJlc2V0ICsgZ2V0Qm91bmRpbmdDbGllbnRSZWN0ID0gMTAwJSByZWxpYWJsZTtcbiAgICAgKiAtIGlPUyBTYWZhcmkgMTQuMDogb2Zmc2V0V2lkdGggPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gaU9TIFNhZmFyaSAxNC4wOiBnZXRCb3VuZGluZ0NsaWVudFJlY3QgPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gQ2hyb21lIDQyLCA2NSwgODAsIDg3OiB6b29tIDEvZGV2aWNlUGl4ZWxSYXRpbyArIG9mZnNldFdpZHRoID0gMXB4IGZsdWN0dWF0aW9uO1xuICAgICAqIC0gQ2hyb21lIDQyLCA2NSwgODAsIDg3OiB6b29tIDEvZGV2aWNlUGl4ZWxSYXRpbyArIGdldEJvdW5kaW5nQ2xpZW50UmVjdCA9IDEwMCUgcmVsaWFibGU7XG4gICAgICogLSBDaHJvbWUgODc6IG9mZnNldFdpZHRoID0gMXB4IGZsdWN0dWF0aW9uO1xuICAgICAqIC0gQ2hyb21lIDg3OiBnZXRCb3VuZGluZ0NsaWVudFJlY3QgPSAwLjdweCBmbHVjdHVhdGlvbjtcbiAgICAgKiAtIEZpcmVmb3ggNDgsIDUxOiBvZmZzZXRXaWR0aCA9IDEwJSBmbHVjdHVhdGlvbjtcbiAgICAgKiAtIEZpcmVmb3ggNDgsIDUxOiBnZXRCb3VuZGluZ0NsaWVudFJlY3QgPSAxMCUgZmx1Y3R1YXRpb247XG4gICAgICogLSBGaXJlZm94IDUyLCA1MywgNTcsIDYyLCA2NiwgNjcsIDY4LCA3MSwgNzUsIDgwLCA4NDogb2Zmc2V0V2lkdGggPSB3aWR0aCAxMDAlIHJlbGlhYmxlLCBoZWlnaHQgMTAlIGZsdWN0dWF0aW9uO1xuICAgICAqIC0gRmlyZWZveCA1MiwgNTMsIDU3LCA2MiwgNjYsIDY3LCA2OCwgNzEsIDc1LCA4MCwgODQ6IGdldEJvdW5kaW5nQ2xpZW50UmVjdCA9IHdpZHRoIDEwMCUgcmVsaWFibGUsIGhlaWdodCAxMCVcbiAgICAgKiAgIGZsdWN0dWF0aW9uO1xuICAgICAqIC0gQW5kcm9pZCBDaHJvbWUgODY6IGhhdmVuJ3QgZm91bmQgYSB3YXkgdG8gem9vbSBhIHBhZ2UgKHBpbmNoIGRvZXNuJ3QgY2hhbmdlIGxheW91dCk7XG4gICAgICogLSBBbmRyb2lkIEZpcmVmb3ggODQ6IGZvbnQgc2l6ZSBpbiBhY2Nlc3NpYmlsaXR5IHNldHRpbmdzIGNoYW5nZXMgYWxsIHRoZSBDU1Mgc2l6ZXMsIGJ1dCBvZmZzZXRXaWR0aCBhbmRcbiAgICAgKiAgIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBrZWVwIG1lYXN1cmluZyB3aXRoIHJlZ3VsYXIgdW5pdHMsIHNvIHRoZSBzaXplIHJlZmxlY3RzIHRoZSBmb250IHNpemUgc2V0dGluZyBhbmQgZG9lc24ndFxuICAgICAqICAgZmx1Y3R1YXRlO1xuICAgICAqIC0gSUUgMTEsIEVkZ2UgMTg6IHpvb20gMS9kZXZpY2VQaXhlbFJhdGlvICsgb2Zmc2V0V2lkdGggPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gSUUgMTEsIEVkZ2UgMTg6IHpvb20gMS9kZXZpY2VQaXhlbFJhdGlvICsgZ2V0Qm91bmRpbmdDbGllbnRSZWN0ID0gcmVmbGVjdHMgdGhlIHpvb20gbGV2ZWw7XG4gICAgICogLSBJRSAxMSwgRWRnZSAxODogb2Zmc2V0V2lkdGggPSAxMDAlIHJlbGlhYmxlO1xuICAgICAqIC0gSUUgMTEsIEVkZ2UgMTg6IGdldEJvdW5kaW5nQ2xpZW50UmVjdCA9IDEwMCUgcmVsaWFibGU7XG4gICAgICovXG4gICAgcmV0dXJuIHdpdGhJZnJhbWUoKF8sIGlmcmFtZVdpbmRvdykgPT4ge1xuICAgICAgICBjb25zdCBpZnJhbWVEb2N1bWVudCA9IGlmcmFtZVdpbmRvdy5kb2N1bWVudDtcbiAgICAgICAgY29uc3QgaWZyYW1lQm9keSA9IGlmcmFtZURvY3VtZW50LmJvZHk7XG4gICAgICAgIGNvbnN0IGJvZHlTdHlsZSA9IGlmcmFtZUJvZHkuc3R5bGU7XG4gICAgICAgIGJvZHlTdHlsZS53aWR0aCA9IGAke2NvbnRhaW5lcldpZHRoUHh9cHhgO1xuICAgICAgICBib2R5U3R5bGUud2Via2l0VGV4dFNpemVBZGp1c3QgPSBib2R5U3R5bGUudGV4dFNpemVBZGp1c3QgPSAnbm9uZSc7XG4gICAgICAgIC8vIFNlZSB0aGUgYmlnIGNvbW1lbnQgYWJvdmVcbiAgICAgICAgaWYgKGlzQ2hyb21pdW0oKSkge1xuICAgICAgICAgICAgaWZyYW1lQm9keS5zdHlsZS56b29tID0gYCR7MSAvIGlmcmFtZVdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvfWA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNXZWJLaXQoKSkge1xuICAgICAgICAgICAgaWZyYW1lQm9keS5zdHlsZS56b29tID0gJ3Jlc2V0JztcbiAgICAgICAgfVxuICAgICAgICAvLyBTZWUgdGhlIGJpZyBjb21tZW50IGFib3ZlXG4gICAgICAgIGNvbnN0IGxpbmVzT2ZUZXh0ID0gaWZyYW1lRG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGxpbmVzT2ZUZXh0LnRleHRDb250ZW50ID0gWy4uLkFycmF5KChjb250YWluZXJXaWR0aFB4IC8gMjApIDw8IDApXS5tYXAoKCkgPT4gJ3dvcmQnKS5qb2luKCcgJyk7XG4gICAgICAgIGlmcmFtZUJvZHkuYXBwZW5kQ2hpbGQobGluZXNPZlRleHQpO1xuICAgICAgICByZXR1cm4gYWN0aW9uKGlmcmFtZURvY3VtZW50LCBpZnJhbWVCb2R5KTtcbiAgICB9LCAnPCFkb2N0eXBlIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgbmFtZT1cInZpZXdwb3J0XCIgY29udGVudD1cIndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xXCI+Jyk7XG59XG5cbmZ1bmN0aW9uIGlzUGRmVmlld2VyRW5hYmxlZCgpIHtcbiAgICByZXR1cm4gbmF2aWdhdG9yLnBkZlZpZXdlckVuYWJsZWQ7XG59XG5cbi8qKlxuICogVW5saWtlIG1vc3Qgb3RoZXIgYXJjaGl0ZWN0dXJlcywgb24geDg2L3g4Ni02NCB3aGVuIGZsb2F0aW5nLXBvaW50IGluc3RydWN0aW9uc1xuICogaGF2ZSBubyBOYU4gYXJndW1lbnRzLCBidXQgcHJvZHVjZSBOYU4gb3V0cHV0LCB0aGUgb3V0cHV0IE5hTiBoYXMgc2lnbiBiaXQgc2V0LlxuICogV2UgdXNlIGl0IHRvIGRpc3Rpbmd1aXNoIHg4Ni94ODYtNjQgZnJvbSBvdGhlciBhcmNoaXRlY3R1cmVzLCBieSBkb2luZyBzdWJ0cmFjdGlvblxuICogb2YgdHdvIGluZmluaXRpZXMgKG11c3QgcHJvZHVjZSBOYU4gcGVyIElFRUUgNzU0IHN0YW5kYXJkKS5cbiAqXG4gKiBTZWUgaHR0cHM6Ly9jb2RlYnJvd3Nlci5iZGRwcHEuY29tL3B5dG9yY2gvcHl0b3JjaC90aGlyZF9wYXJ0eS9YTk5QQUNLL3NyYy9pbml0LmMuaHRtbCM3OVxuICovXG5mdW5jdGlvbiBnZXRBcmNoaXRlY3R1cmUoKSB7XG4gICAgY29uc3QgZiA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7XG4gICAgY29uc3QgdTggPSBuZXcgVWludDhBcnJheShmLmJ1ZmZlcik7XG4gICAgZlswXSA9IEluZmluaXR5O1xuICAgIGZbMF0gPSBmWzBdIC0gZlswXTtcbiAgICByZXR1cm4gdThbM107XG59XG5cbi8qKlxuICogVGhlIHJldHVybiB0eXBlIGlzIGEgdW5pb24gaW5zdGVhZCBvZiB0aGUgZW51bSwgYmVjYXVzZSBpdCdzIHRvbyBjaGFsbGVuZ2luZyB0byBlbWJlZCB0aGUgY29uc3QgZW51bSBpbnRvIGFub3RoZXJcbiAqIHByb2plY3QuIFR1cm5pbmcgaXQgaW50byBhIHVuaW9uIGlzIGEgc2ltcGxlIGFuZCBhbiBlbGVnYW50IHNvbHV0aW9uLlxuICovXG5mdW5jdGlvbiBnZXRBcHBsZVBheVN0YXRlKCkge1xuICAgIGNvbnN0IHsgQXBwbGVQYXlTZXNzaW9uIH0gPSB3aW5kb3c7XG4gICAgaWYgKHR5cGVvZiAoQXBwbGVQYXlTZXNzaW9uID09PSBudWxsIHx8IEFwcGxlUGF5U2Vzc2lvbiA9PT0gdm9pZCAwID8gdm9pZCAwIDogQXBwbGVQYXlTZXNzaW9uLmNhbk1ha2VQYXltZW50cykgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIC0xIC8qIEFwcGxlUGF5U3RhdGUuTm9BUEkgKi87XG4gICAgfVxuICAgIGlmICh3aWxsUHJpbnRDb25zb2xlRXJyb3IoKSkge1xuICAgICAgICByZXR1cm4gLTMgLyogQXBwbGVQYXlTdGF0ZS5Ob3RBdmFpbGFibGVJbkZyYW1lICovO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gQXBwbGVQYXlTZXNzaW9uLmNhbk1ha2VQYXltZW50cygpID8gMSAvKiBBcHBsZVBheVN0YXRlLkVuYWJsZWQgKi8gOiAwIC8qIEFwcGxlUGF5U3RhdGUuRGlzYWJsZWQgKi87XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICByZXR1cm4gZ2V0U3RhdGVGcm9tRXJyb3IoZXJyb3IpO1xuICAgIH1cbn1cbi8qKlxuICogU3RhcnRpbmcgZnJvbSBTYWZhcmkgMTUgY2FsbGluZyBgQXBwbGVQYXlTZXNzaW9uLmNhbk1ha2VQYXltZW50cygpYCBwcm9kdWNlcyB0aGlzIGVycm9yIG1lc3NhZ2Ugd2hlbiBGaW5nZXJwcmludEpTXG4gKiBydW5zIGluIGFuIGlmcmFtZSB3aXRoIGEgY3Jvc3Mtb3JpZ2luIHBhcmVudCBwYWdlLCBhbmQgdGhlIGlmcmFtZSBvbiB0aGF0IHBhZ2UgaGFzIG5vIGFsbG93PVwicGF5bWVudCAqXCIgYXR0cmlidXRlOlxuICogICBGZWF0dXJlIHBvbGljeSAnUGF5bWVudCcgY2hlY2sgZmFpbGVkIGZvciBlbGVtZW50IHdpdGggb3JpZ2luICdodHRwczovL2V4YW1wbGUuY29tJyBhbmQgYWxsb3cgYXR0cmlidXRlICcnLlxuICogVGhpcyBmdW5jdGlvbiBjaGVja3Mgd2hldGhlciB0aGUgZXJyb3IgbWVzc2FnZSBpcyBleHBlY3RlZC5cbiAqXG4gKiBXZSBjaGVjayBmb3IgY3Jvc3Mtb3JpZ2luIHBhcmVudHMsIHdoaWNoIGlzIHByb25lIHRvIGZhbHNlLXBvc2l0aXZlIHJlc3VsdHMuIEluc3RlYWQsIHdlIHNob3VsZCBjaGVjayBmb3IgYWxsb3dlZFxuICogZmVhdHVyZS9wZXJtaXNzaW9uLCBidXQgd2UgY2FuJ3QgYmVjYXVzZSBub25lIG9mIHRoZXNlIEFQSSB3b3JrcyBpbiBTYWZhcmkgeWV0OlxuICogICBuYXZpZ2F0b3IucGVybWlzc2lvbnMucXVlcnkoeyBuYW1lOiBcdTIwMThwYXltZW50JyB9KVxuICogICBuYXZpZ2F0b3IucGVybWlzc2lvbnMucXVlcnkoeyBuYW1lOiBcdTIwMThwYXltZW50LWhhbmRsZXInIH0pXG4gKiAgIGRvY3VtZW50LmZlYXR1cmVQb2xpY3lcbiAqL1xuY29uc3Qgd2lsbFByaW50Q29uc29sZUVycm9yID0gaXNBbnlQYXJlbnRDcm9zc09yaWdpbjtcbmZ1bmN0aW9uIGdldFN0YXRlRnJvbUVycm9yKGVycm9yKSB7XG4gICAgLy8gU2VlIGZ1bGwgZXhwZWN0ZWQgZXJyb3IgbWVzc2FnZXMgaW4gdGhlIHRlc3RcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5uYW1lID09PSAnSW52YWxpZEFjY2Vzc0Vycm9yJyAmJiAvXFxiZnJvbVxcYi4qXFxiaW5zZWN1cmVcXGIvaS50ZXN0KGVycm9yLm1lc3NhZ2UpKSB7XG4gICAgICAgIHJldHVybiAtMiAvKiBBcHBsZVBheVN0YXRlLk5vdEF2YWlsYWJsZUluSW5zZWN1cmVDb250ZXh0ICovO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgU2FmYXJpJ3MgUHJpdmFjeSBQcmVzZXJ2aW5nIEFkIE1lYXN1cmVtZW50IHNldHRpbmcgaXMgb24uXG4gKiBUaGUgc2V0dGluZyBpcyBvbiB3aGVuIHRoZSB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkLlxuICogQS5rLmEuIHByaXZhdGUgY2xpY2sgbWVhc3VyZW1lbnQsIHByaXZhY3ktcHJlc2VydmluZyBhZCBhdHRyaWJ1dGlvbi5cbiAqXG4gKiBVbmZvcnR1bmF0ZWx5LCBpdCBkb2Vzbid0IHdvcmsgaW4gbW9iaWxlIFNhZmFyaS5cbiAqIFByb2JhYmx5LCBpdCB3aWxsIHN0YXJ0IHdvcmtpbmcgaW4gbW9iaWxlIFNhZmFyaSBvciBzdG9wIHdvcmtpbmcgaW4gZGVza3RvcCBTYWZhcmkgbGF0ZXIuXG4gKiBXZSd2ZSBmb3VuZCBubyB3YXkgdG8gZGV0ZWN0IHRoZSBzZXR0aW5nIHN0YXRlIGluIG1vYmlsZSBTYWZhcmkuIEhlbHAgd2FudGVkLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly93ZWJraXQub3JnL2Jsb2cvMTE1MjkvaW50cm9kdWNpbmctcHJpdmF0ZS1jbGljay1tZWFzdXJlbWVudC1wY20vXG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLmFwcGxlLmNvbS92aWRlb3MvcGxheS93d2RjMjAyMS8xMDAzM1xuICovXG5mdW5jdGlvbiBnZXRQcml2YXRlQ2xpY2tNZWFzdXJlbWVudCgpIHtcbiAgICB2YXIgX2E7XG4gICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICBjb25zdCBzb3VyY2VJZCA9IChfYSA9IGxpbmsuYXR0cmlidXRpb25Tb3VyY2VJZCkgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogbGluay5hdHRyaWJ1dGlvbnNvdXJjZWlkO1xuICAgIHJldHVybiBzb3VyY2VJZCA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogU3RyaW5nKHNvdXJjZUlkKTtcbn1cblxuLyoqIFdlYkdsIGNvbnRleHQgaXMgbm90IGF2YWlsYWJsZSAqL1xuY29uc3QgU1RBVFVTX05PX0dMX0NPTlRFWFQgPSAtMTtcbi8qKiBXZWJHTCBjb250ZXh0IGBnZXRQYXJhbWV0ZXJgIG1ldGhvZCBpcyBub3QgYSBmdW5jdGlvbiAqL1xuY29uc3QgU1RBVFVTX0dFVF9QQVJBTUVURVJfTk9UX0FfRlVOQ1RJT04gPSAtMjtcbmNvbnN0IHZhbGlkQ29udGV4dFBhcmFtZXRlcnMgPSBuZXcgU2V0KFtcbiAgICAxMDc1MiwgMjg0OSwgMjg4NCwgMjg4NSwgMjg4NiwgMjkyOCwgMjkyOSwgMjkzMCwgMjkzMSwgMjkzMiwgMjk2MCwgMjk2MSwgMjk2MiwgMjk2MywgMjk2NCwgMjk2NSwgMjk2NiwgMjk2NywgMjk2OCxcbiAgICAyOTc4LCAzMDI0LCAzMDQyLCAzMDg4LCAzMDg5LCAzMTA2LCAzMTA3LCAzMjc3MywgMzI3NzcsIDMyNzc3LCAzMjgyMywgMzI4MjQsIDMyOTM2LCAzMjkzNywgMzI5MzgsIDMyOTM5LCAzMjk2OCwgMzI5NjksXG4gICAgMzI5NzAsIDMyOTcxLCAzMzE3LCAzMzE3MCwgMzMzMywgMzM3OSwgMzM4NiwgMzM5MDEsIDMzOTAyLCAzNDAxNiwgMzQwMjQsIDM0MDc2LCAzNDA4LCAzNDEwLCAzNDExLCAzNDEyLCAzNDEzLCAzNDE0LFxuICAgIDM0MTUsIDM0NDY3LCAzNDgxNiwgMzQ4MTcsIDM0ODE4LCAzNDgxOSwgMzQ4NzcsIDM0OTIxLCAzNDkzMCwgMzU2NjAsIDM1NjYxLCAzNTcyNCwgMzU3MzgsIDM1NzM5LCAzNjAwMywgMzYwMDQsIDM2MDA1LFxuICAgIDM2MzQ3LCAzNjM0OCwgMzYzNDksIDM3NDQwLCAzNzQ0MSwgMzc0NDMsIDc5MzYsIDc5MzcsIDc5MzgsXG4gICAgLy8gU0FNUExFX0FMUEhBX1RPX0NPVkVSQUdFICgzMjkyNikgYW5kIFNBTVBMRV9DT1ZFUkFHRSAoMzI5MjgpIGFyZSBleGNsdWRlZCBiZWNhdXNlIHRoZXkgdHJpZ2dlciBhIGNvbnNvbGUgd2FybmluZ1xuICAgIC8vIGluIElFLCBDaHJvbWUgXHUyMjY0IDU5IGFuZCBTYWZhcmkgXHUyMjY0IDEzIGFuZCBnaXZlIG5vIGVudHJvcHkuXG5dKTtcbmNvbnN0IHZhbGlkRXh0ZW5zaW9uUGFyYW1zID0gbmV3IFNldChbXG4gICAgMzQwNDcsXG4gICAgMzU3MjMsXG4gICAgMzYwNjMsXG4gICAgMzQ4NTIsXG4gICAgMzQ4NTMsXG4gICAgMzQ4NTQsXG4gICAgMzQyMjksXG4gICAgMzYzOTIsXG4gICAgMzY3OTUsXG4gICAgMzg0NDksIC8vIE1BWF9WSUVXU19PVlJcbl0pO1xuY29uc3Qgc2hhZGVyVHlwZXMgPSBbJ0ZSQUdNRU5UX1NIQURFUicsICdWRVJURVhfU0hBREVSJ107XG5jb25zdCBwcmVjaXNpb25UeXBlcyA9IFsnTE9XX0ZMT0FUJywgJ01FRElVTV9GTE9BVCcsICdISUdIX0ZMT0FUJywgJ0xPV19JTlQnLCAnTUVESVVNX0lOVCcsICdISUdIX0lOVCddO1xuY29uc3QgcmVuZGVyZXJJbmZvRXh0ZW5zaW9uTmFtZSA9ICdXRUJHTF9kZWJ1Z19yZW5kZXJlcl9pbmZvJztcbmNvbnN0IHBvbHlnb25Nb2RlRXh0ZW5zaW9uTmFtZSA9ICdXRUJHTF9wb2x5Z29uX21vZGUnO1xuLyoqXG4gKiBHZXRzIHRoZSBiYXNpYyBhbmQgc2ltcGxlIFdlYkdMIHBhcmFtZXRlcnNcbiAqL1xuZnVuY3Rpb24gZ2V0V2ViR2xCYXNpY3MoeyBjYWNoZSB9KSB7XG4gICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2Y7XG4gICAgY29uc3QgZ2wgPSBnZXRXZWJHTENvbnRleHQoY2FjaGUpO1xuICAgIGlmICghZ2wpIHtcbiAgICAgICAgcmV0dXJuIFNUQVRVU19OT19HTF9DT05URVhUO1xuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRQYXJhbWV0ZXJHZXR0ZXIoZ2wpKSB7XG4gICAgICAgIHJldHVybiBTVEFUVVNfR0VUX1BBUkFNRVRFUl9OT1RfQV9GVU5DVElPTjtcbiAgICB9XG4gICAgY29uc3QgZGVidWdFeHRlbnNpb24gPSBzaG91bGRBdm9pZERlYnVnUmVuZGVyZXJJbmZvKCkgPyBudWxsIDogZ2wuZ2V0RXh0ZW5zaW9uKHJlbmRlcmVySW5mb0V4dGVuc2lvbk5hbWUpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHZlcnNpb246ICgoX2EgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuVkVSU0lPTikpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS50b1N0cmluZygpKSB8fCAnJyxcbiAgICAgICAgdmVuZG9yOiAoKF9iID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLlZFTkRPUikpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi50b1N0cmluZygpKSB8fCAnJyxcbiAgICAgICAgdmVuZG9yVW5tYXNrZWQ6IGRlYnVnRXh0ZW5zaW9uID8gKF9jID0gZ2wuZ2V0UGFyYW1ldGVyKGRlYnVnRXh0ZW5zaW9uLlVOTUFTS0VEX1ZFTkRPUl9XRUJHTCkpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy50b1N0cmluZygpIDogJycsXG4gICAgICAgIHJlbmRlcmVyOiAoKF9kID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLlJFTkRFUkVSKSkgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLnRvU3RyaW5nKCkpIHx8ICcnLFxuICAgICAgICByZW5kZXJlclVubWFza2VkOiBkZWJ1Z0V4dGVuc2lvbiA/IChfZSA9IGdsLmdldFBhcmFtZXRlcihkZWJ1Z0V4dGVuc2lvbi5VTk1BU0tFRF9SRU5ERVJFUl9XRUJHTCkpID09PSBudWxsIHx8IF9lID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZS50b1N0cmluZygpIDogJycsXG4gICAgICAgIHNoYWRpbmdMYW5ndWFnZVZlcnNpb246ICgoX2YgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuU0hBRElOR19MQU5HVUFHRV9WRVJTSU9OKSkgPT09IG51bGwgfHwgX2YgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9mLnRvU3RyaW5nKCkpIHx8ICcnLFxuICAgIH07XG59XG4vKipcbiAqIEdldHMgdGhlIGFkdmFuY2VkIGFuZCBtYXNzaXZlIFdlYkdMIHBhcmFtZXRlcnMgYW5kIGV4dGVuc2lvbnNcbiAqL1xuZnVuY3Rpb24gZ2V0V2ViR2xFeHRlbnNpb25zKHsgY2FjaGUgfSkge1xuICAgIGNvbnN0IGdsID0gZ2V0V2ViR0xDb250ZXh0KGNhY2hlKTtcbiAgICBpZiAoIWdsKSB7XG4gICAgICAgIHJldHVybiBTVEFUVVNfTk9fR0xfQ09OVEVYVDtcbiAgICB9XG4gICAgaWYgKCFpc1ZhbGlkUGFyYW1ldGVyR2V0dGVyKGdsKSkge1xuICAgICAgICByZXR1cm4gU1RBVFVTX0dFVF9QQVJBTUVURVJfTk9UX0FfRlVOQ1RJT047XG4gICAgfVxuICAgIGNvbnN0IGV4dGVuc2lvbnMgPSBnbC5nZXRTdXBwb3J0ZWRFeHRlbnNpb25zKCk7XG4gICAgY29uc3QgY29udGV4dEF0dHJpYnV0ZXMgPSBnbC5nZXRDb250ZXh0QXR0cmlidXRlcygpO1xuICAgIGNvbnN0IHVuc3VwcG9ydGVkRXh0ZW5zaW9ucyA9IFtdO1xuICAgIC8vIEZlYXR1cmVzXG4gICAgY29uc3QgYXR0cmlidXRlcyA9IFtdO1xuICAgIGNvbnN0IHBhcmFtZXRlcnMgPSBbXTtcbiAgICBjb25zdCBleHRlbnNpb25QYXJhbWV0ZXJzID0gW107XG4gICAgY29uc3Qgc2hhZGVyUHJlY2lzaW9ucyA9IFtdO1xuICAgIC8vIENvbnRleHQgYXR0cmlidXRlc1xuICAgIGlmIChjb250ZXh0QXR0cmlidXRlcykge1xuICAgICAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZU5hbWUgb2YgT2JqZWN0LmtleXMoY29udGV4dEF0dHJpYnV0ZXMpKSB7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzLnB1c2goYCR7YXR0cmlidXRlTmFtZX09JHtjb250ZXh0QXR0cmlidXRlc1thdHRyaWJ1dGVOYW1lXX1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBDb250ZXh0IHBhcmFtZXRlcnNcbiAgICBjb25zdCBjb25zdGFudHMgPSBnZXRDb25zdGFudHNGcm9tUHJvdG90eXBlKGdsKTtcbiAgICBmb3IgKGNvbnN0IGNvbnN0YW50IG9mIGNvbnN0YW50cykge1xuICAgICAgICBjb25zdCBjb2RlID0gZ2xbY29uc3RhbnRdO1xuICAgICAgICBwYXJhbWV0ZXJzLnB1c2goYCR7Y29uc3RhbnR9PSR7Y29kZX0ke3ZhbGlkQ29udGV4dFBhcmFtZXRlcnMuaGFzKGNvZGUpID8gYD0ke2dsLmdldFBhcmFtZXRlcihjb2RlKX1gIDogJyd9YCk7XG4gICAgfVxuICAgIC8vIEV4dGVuc2lvbiBwYXJhbWV0ZXJzXG4gICAgaWYgKGV4dGVuc2lvbnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIGV4dGVuc2lvbnMpIHtcbiAgICAgICAgICAgIGlmICgobmFtZSA9PT0gcmVuZGVyZXJJbmZvRXh0ZW5zaW9uTmFtZSAmJiBzaG91bGRBdm9pZERlYnVnUmVuZGVyZXJJbmZvKCkpIHx8XG4gICAgICAgICAgICAgICAgKG5hbWUgPT09IHBvbHlnb25Nb2RlRXh0ZW5zaW9uTmFtZSAmJiBzaG91bGRBdm9pZFBvbHlnb25Nb2RlRXh0ZW5zaW9ucygpKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gZ2wuZ2V0RXh0ZW5zaW9uKG5hbWUpO1xuICAgICAgICAgICAgaWYgKCFleHRlbnNpb24pIHtcbiAgICAgICAgICAgICAgICB1bnN1cHBvcnRlZEV4dGVuc2lvbnMucHVzaChuYW1lKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoY29uc3QgY29uc3RhbnQgb2YgZ2V0Q29uc3RhbnRzRnJvbVByb3RvdHlwZShleHRlbnNpb24pKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29kZSA9IGV4dGVuc2lvbltjb25zdGFudF07XG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uUGFyYW1ldGVycy5wdXNoKGAke2NvbnN0YW50fT0ke2NvZGV9JHt2YWxpZEV4dGVuc2lvblBhcmFtcy5oYXMoY29kZSkgPyBgPSR7Z2wuZ2V0UGFyYW1ldGVyKGNvZGUpfWAgOiAnJ31gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBTaGFkZXIgcHJlY2lzaW9uXG4gICAgZm9yIChjb25zdCBzaGFkZXJUeXBlIG9mIHNoYWRlclR5cGVzKSB7XG4gICAgICAgIGZvciAoY29uc3QgcHJlY2lzaW9uVHlwZSBvZiBwcmVjaXNpb25UeXBlcykge1xuICAgICAgICAgICAgY29uc3Qgc2hhZGVyUHJlY2lzaW9uID0gZ2V0U2hhZGVyUHJlY2lzaW9uKGdsLCBzaGFkZXJUeXBlLCBwcmVjaXNpb25UeXBlKTtcbiAgICAgICAgICAgIHNoYWRlclByZWNpc2lvbnMucHVzaChgJHtzaGFkZXJUeXBlfS4ke3ByZWNpc2lvblR5cGV9PSR7c2hhZGVyUHJlY2lzaW9uLmpvaW4oJywnKX1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBQb3N0cHJvY2Vzc1xuICAgIGV4dGVuc2lvblBhcmFtZXRlcnMuc29ydCgpO1xuICAgIHBhcmFtZXRlcnMuc29ydCgpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRleHRBdHRyaWJ1dGVzOiBhdHRyaWJ1dGVzLFxuICAgICAgICBwYXJhbWV0ZXJzOiBwYXJhbWV0ZXJzLFxuICAgICAgICBzaGFkZXJQcmVjaXNpb25zOiBzaGFkZXJQcmVjaXNpb25zLFxuICAgICAgICBleHRlbnNpb25zOiBleHRlbnNpb25zLFxuICAgICAgICBleHRlbnNpb25QYXJhbWV0ZXJzOiBleHRlbnNpb25QYXJhbWV0ZXJzLFxuICAgICAgICB1bnN1cHBvcnRlZEV4dGVuc2lvbnMsXG4gICAgfTtcbn1cbi8qKlxuICogVGhpcyBmdW5jdGlvbiB1c3VhbGx5IHRha2VzIHRoZSBtb3N0IHRpbWUgdG8gZXhlY3V0ZSBpbiBhbGwgdGhlIHNvdXJjZXMsIHRoZXJlZm9yZSB3ZSBjYWNoZSBpdHMgcmVzdWx0LlxuICpcbiAqIFdhcm5pbmcgZm9yIHBhY2thZ2UgdXNlcnM6XG4gKiBUaGlzIGZ1bmN0aW9uIGlzIG91dCBvZiBTZW1hbnRpYyBWZXJzaW9uaW5nLCBpLmUuIGNhbiBjaGFuZ2UgdW5leHBlY3RlZGx5LiBVc2FnZSBpcyBhdCB5b3VyIG93biByaXNrLlxuICovXG5mdW5jdGlvbiBnZXRXZWJHTENvbnRleHQoY2FjaGUpIHtcbiAgICBpZiAoY2FjaGUud2ViZ2wpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlLndlYmdsLmNvbnRleHQ7XG4gICAgfVxuICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIGxldCBjb250ZXh0O1xuICAgIGNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbENyZWF0ZUNvbnRleHRFcnJvcicsICgpID0+IChjb250ZXh0ID0gdW5kZWZpbmVkKSk7XG4gICAgZm9yIChjb25zdCB0eXBlIG9mIFsnd2ViZ2wnLCAnZXhwZXJpbWVudGFsLXdlYmdsJ10pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCh0eXBlKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoX2EpIHtcbiAgICAgICAgICAgIC8vIE9rLCBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGlmIChjb250ZXh0KSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBjYWNoZS53ZWJnbCA9IHsgY29udGV4dCB9O1xuICAgIHJldHVybiBjb250ZXh0O1xufVxuLyoqXG4gKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2ViR0xTaGFkZXJQcmVjaXNpb25Gb3JtYXRcbiAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XZWJHTFJlbmRlcmluZ0NvbnRleHQvZ2V0U2hhZGVyUHJlY2lzaW9uRm9ybWF0XG4gKiBodHRwczovL3d3dy5raHJvbm9zLm9yZy9yZWdpc3RyeS93ZWJnbC9zcGVjcy9sYXRlc3QvMS4wLyM1LjEyXG4gKi9cbmZ1bmN0aW9uIGdldFNoYWRlclByZWNpc2lvbihnbCwgc2hhZGVyVHlwZSwgcHJlY2lzaW9uVHlwZSkge1xuICAgIGNvbnN0IHNoYWRlclByZWNpc2lvbiA9IGdsLmdldFNoYWRlclByZWNpc2lvbkZvcm1hdChnbFtzaGFkZXJUeXBlXSwgZ2xbcHJlY2lzaW9uVHlwZV0pO1xuICAgIHJldHVybiBzaGFkZXJQcmVjaXNpb24gPyBbc2hhZGVyUHJlY2lzaW9uLnJhbmdlTWluLCBzaGFkZXJQcmVjaXNpb24ucmFuZ2VNYXgsIHNoYWRlclByZWNpc2lvbi5wcmVjaXNpb25dIDogW107XG59XG5mdW5jdGlvbiBnZXRDb25zdGFudHNGcm9tUHJvdG90eXBlKG9iaikge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iai5fX3Byb3RvX18pO1xuICAgIHJldHVybiBrZXlzLmZpbHRlcihpc0NvbnN0YW50TGlrZSk7XG59XG5mdW5jdGlvbiBpc0NvbnN0YW50TGlrZShrZXkpIHtcbiAgICByZXR1cm4gdHlwZW9mIGtleSA9PT0gJ3N0cmluZycgJiYgIWtleS5tYXRjaCgvW15BLVowLTlfeF0vKTtcbn1cbi8qKlxuICogU29tZSBicm93c2VycyBwcmludCBhIGNvbnNvbGUgd2FybmluZyB3aGVuIHRoZSBXRUJHTF9kZWJ1Z19yZW5kZXJlcl9pbmZvIGV4dGVuc2lvbiBpcyByZXF1ZXN0ZWQuXG4gKiBKUyBBZ2VudCBhaW1zIHRvIGF2b2lkIHByaW50aW5nIG1lc3NhZ2VzIHRvIGNvbnNvbGUsIHNvIHdlIGF2b2lkIHRoaXMgZXh0ZW5zaW9uIGluIHRoYXQgYnJvd3NlcnMuXG4gKi9cbmZ1bmN0aW9uIHNob3VsZEF2b2lkRGVidWdSZW5kZXJlckluZm8oKSB7XG4gICAgcmV0dXJuIGlzR2Vja28oKTtcbn1cbi8qKlxuICogU29tZSBicm93c2VycyBwcmludCBhIGNvbnNvbGUgd2FybmluZyB3aGVuIHRoZSBXRUJHTF9wb2x5Z29uX21vZGUgZXh0ZW5zaW9uIGlzIHJlcXVlc3RlZC5cbiAqIEpTIEFnZW50IGFpbXMgdG8gYXZvaWQgcHJpbnRpbmcgbWVzc2FnZXMgdG8gY29uc29sZSwgc28gd2UgYXZvaWQgdGhpcyBleHRlbnNpb24gaW4gdGhhdCBicm93c2Vycy5cbiAqL1xuZnVuY3Rpb24gc2hvdWxkQXZvaWRQb2x5Z29uTW9kZUV4dGVuc2lvbnMoKSB7XG4gICAgcmV0dXJuIGlzQ2hyb21pdW0oKSB8fCBpc1dlYktpdCgpO1xufVxuLyoqXG4gKiBTb21lIHVua25vd24gYnJvd3NlcnMgaGF2ZSBubyBgZ2V0UGFyYW1ldGVyYCBtZXRob2RcbiAqL1xuZnVuY3Rpb24gaXNWYWxpZFBhcmFtZXRlckdldHRlcihnbCkge1xuICAgIHJldHVybiB0eXBlb2YgZ2wuZ2V0UGFyYW1ldGVyID09PSAnZnVuY3Rpb24nO1xufVxuXG5mdW5jdGlvbiBnZXRBdWRpb0NvbnRleHRCYXNlTGF0ZW5jeSgpIHtcbiAgICAvLyBUaGUgc2lnbmFsIGVtaXRzIHdhcm5pbmcgaW4gQ2hyb21lIGFuZCBGaXJlZm94LCB0aGVyZWZvcmUgaXQgaXMgZW5hYmxlZCBvbiBTYWZhcmkgd2hlcmUgaXQgZG9lc24ndCBwcm9kdWNlIHdhcm5pbmdcbiAgICAvLyBhbmQgb24gQW5kcm9pZCB3aGVyZSBpdCdzIGxlc3MgdmlzaWJsZVxuICAgIGNvbnN0IGlzQWxsb3dlZFBsYXRmb3JtID0gaXNBbmRyb2lkKCkgfHwgaXNXZWJLaXQoKTtcbiAgICBpZiAoIWlzQWxsb3dlZFBsYXRmb3JtKSB7XG4gICAgICAgIHJldHVybiAtMiAvKiBTcGVjaWFsRmluZ2VycHJpbnQuRGlzYWJsZWQgKi87XG4gICAgfVxuICAgIGlmICghd2luZG93LkF1ZGlvQ29udGV4dCkge1xuICAgICAgICByZXR1cm4gLTEgLyogU3BlY2lhbEZpbmdlcnByaW50Lk5vdFN1cHBvcnRlZCAqLztcbiAgICB9XG4gICAgY29uc3QgbGF0ZW5jeSA9IG5ldyBBdWRpb0NvbnRleHQoKS5iYXNlTGF0ZW5jeTtcbiAgICBpZiAobGF0ZW5jeSA9PT0gbnVsbCB8fCBsYXRlbmN5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIC0xIC8qIFNwZWNpYWxGaW5nZXJwcmludC5Ob3RTdXBwb3J0ZWQgKi87XG4gICAgfVxuICAgIGlmICghaXNGaW5pdGUobGF0ZW5jeSkpIHtcbiAgICAgICAgcmV0dXJuIC0zIC8qIFNwZWNpYWxGaW5nZXJwcmludC5Ob3RGaW5pdGUgKi87XG4gICAgfVxuICAgIHJldHVybiBsYXRlbmN5O1xufVxuXG4vKipcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvSW50bC9EYXRlVGltZUZvcm1hdC9yZXNvbHZlZE9wdGlvbnNcbiAqXG4gKiBUaGUgcmV0dXJuIHR5cGUgaXMgYSB1bmlvbiBpbnN0ZWFkIG9mIGEgY29uc3QgZW51bSBkdWUgdG8gdGhlIGRpZmZpY3VsdHkgb2YgZW1iZWRkaW5nIGNvbnN0IGVudW1zIGluIG90aGVyIHByb2plY3RzLlxuICogVGhpcyBtYWtlcyBpbnRlZ3JhdGlvbiBzaW1wbGVyIGFuZCBtb3JlIGVsZWdhbnQuXG4gKi9cbmZ1bmN0aW9uIGdldERhdGVUaW1lTG9jYWxlKCkge1xuICAgIGlmICghd2luZG93LkludGwpIHtcbiAgICAgICAgcmV0dXJuIC0xIC8qIFN0YXR1cy5JbnRsQVBJTm90U3VwcG9ydGVkICovO1xuICAgIH1cbiAgICBjb25zdCBEYXRlVGltZUZvcm1hdCA9IHdpbmRvdy5JbnRsLkRhdGVUaW1lRm9ybWF0O1xuICAgIGlmICghRGF0ZVRpbWVGb3JtYXQpIHtcbiAgICAgICAgcmV0dXJuIC0yIC8qIFN0YXR1cy5EYXRlVGltZUZvcm1hdE5vdFN1cHBvcnRlZCAqLztcbiAgICB9XG4gICAgY29uc3QgbG9jYWxlID0gRGF0ZVRpbWVGb3JtYXQoKS5yZXNvbHZlZE9wdGlvbnMoKS5sb2NhbGU7XG4gICAgaWYgKCFsb2NhbGUgJiYgbG9jYWxlICE9PSAnJykge1xuICAgICAgICByZXR1cm4gLTMgLyogU3RhdHVzLkxvY2FsZU5vdEF2YWlsYWJsZSAqLztcbiAgICB9XG4gICAgcmV0dXJuIGxvY2FsZTtcbn1cblxuLyoqXG4gKiBUaGUgbGlzdCBvZiBlbnRyb3B5IHNvdXJjZXMgdXNlZCB0byBtYWtlIHZpc2l0b3IgaWRlbnRpZmllcnMuXG4gKlxuICogVGhpcyB2YWx1ZSBpc24ndCByZXN0cmljdGVkIGJ5IFNlbWFudGljIFZlcnNpb25pbmcsIGkuZS4gaXQgbWF5IGJlIGNoYW5nZWQgd2l0aG91dCBidW1waW5nIG1pbm9yIG9yIG1ham9yIHZlcnNpb24gb2ZcbiAqIHRoaXMgcGFja2FnZS5cbiAqXG4gKiBOb3RlOiBSb2xsdXAgYW5kIFdlYnBhY2sgYXJlIHNtYXJ0IGVub3VnaCB0byByZW1vdmUgdW51c2VkIHByb3BlcnRpZXMgb2YgdGhpcyBvYmplY3QgZHVyaW5nIHRyZWUtc2hha2luZywgc28gdGhlcmUgaXNcbiAqIG5vIG5lZWQgdG8gZXhwb3J0IHRoZSBzb3VyY2VzIGluZGl2aWR1YWxseS5cbiAqL1xuY29uc3Qgc291cmNlcyA9IHtcbiAgICAvLyBSRUFEIEZJUlNUOlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2Jsb2IvbWFzdGVyL2NvbnRyaWJ1dGluZy5tZCNob3ctdG8tYWRkLWFuLWVudHJvcHktc291cmNlXG4gICAgLy8gdG8gbGVhcm4gaG93IGVudHJvcHkgc291cmNlIHdvcmtzIGFuZCBob3cgdG8gbWFrZSB5b3VyIG93bi5cbiAgICAvLyBUaGUgc291cmNlcyBydW4gaW4gdGhpcyBleGFjdCBvcmRlci5cbiAgICAvLyBUaGUgYXN5bmNocm9ub3VzIHNvdXJjZXMgYXJlIGF0IHRoZSBzdGFydCB0byBydW4gaW4gcGFyYWxsZWwgd2l0aCBvdGhlciBzb3VyY2VzLlxuICAgIGZvbnRzOiBnZXRGb250cyxcbiAgICBkb21CbG9ja2VyczogZ2V0RG9tQmxvY2tlcnMsXG4gICAgZm9udFByZWZlcmVuY2VzOiBnZXRGb250UHJlZmVyZW5jZXMsXG4gICAgYXVkaW86IGdldEF1ZGlvRmluZ2VycHJpbnQsXG4gICAgc2NyZWVuRnJhbWU6IGdldFNjcmVlbkZyYW1lLFxuICAgIGNhbnZhczogZ2V0Q2FudmFzRmluZ2VycHJpbnQsXG4gICAgb3NDcHU6IGdldE9zQ3B1LFxuICAgIGxhbmd1YWdlczogZ2V0TGFuZ3VhZ2VzLFxuICAgIGNvbG9yRGVwdGg6IGdldENvbG9yRGVwdGgsXG4gICAgZGV2aWNlTWVtb3J5OiBnZXREZXZpY2VNZW1vcnksXG4gICAgc2NyZWVuUmVzb2x1dGlvbjogZ2V0U2NyZWVuUmVzb2x1dGlvbixcbiAgICBoYXJkd2FyZUNvbmN1cnJlbmN5OiBnZXRIYXJkd2FyZUNvbmN1cnJlbmN5LFxuICAgIHRpbWV6b25lOiBnZXRUaW1lem9uZSxcbiAgICBzZXNzaW9uU3RvcmFnZTogZ2V0U2Vzc2lvblN0b3JhZ2UsXG4gICAgbG9jYWxTdG9yYWdlOiBnZXRMb2NhbFN0b3JhZ2UsXG4gICAgaW5kZXhlZERCOiBnZXRJbmRleGVkREIsXG4gICAgb3BlbkRhdGFiYXNlOiBnZXRPcGVuRGF0YWJhc2UsXG4gICAgY3B1Q2xhc3M6IGdldENwdUNsYXNzLFxuICAgIHBsYXRmb3JtOiBnZXRQbGF0Zm9ybSxcbiAgICBwbHVnaW5zOiBnZXRQbHVnaW5zLFxuICAgIHRvdWNoU3VwcG9ydDogZ2V0VG91Y2hTdXBwb3J0LFxuICAgIHZlbmRvcjogZ2V0VmVuZG9yLFxuICAgIHZlbmRvckZsYXZvcnM6IGdldFZlbmRvckZsYXZvcnMsXG4gICAgY29va2llc0VuYWJsZWQ6IGFyZUNvb2tpZXNFbmFibGVkLFxuICAgIGNvbG9yR2FtdXQ6IGdldENvbG9yR2FtdXQsXG4gICAgaW52ZXJ0ZWRDb2xvcnM6IGFyZUNvbG9yc0ludmVydGVkLFxuICAgIGZvcmNlZENvbG9yczogYXJlQ29sb3JzRm9yY2VkLFxuICAgIG1vbm9jaHJvbWU6IGdldE1vbm9jaHJvbWVEZXB0aCxcbiAgICBjb250cmFzdDogZ2V0Q29udHJhc3RQcmVmZXJlbmNlLFxuICAgIHJlZHVjZWRNb3Rpb246IGlzTW90aW9uUmVkdWNlZCxcbiAgICByZWR1Y2VkVHJhbnNwYXJlbmN5OiBpc1RyYW5zcGFyZW5jeVJlZHVjZWQsXG4gICAgaGRyOiBpc0hEUixcbiAgICBtYXRoOiBnZXRNYXRoRmluZ2VycHJpbnQsXG4gICAgcGRmVmlld2VyRW5hYmxlZDogaXNQZGZWaWV3ZXJFbmFibGVkLFxuICAgIGFyY2hpdGVjdHVyZTogZ2V0QXJjaGl0ZWN0dXJlLFxuICAgIGFwcGxlUGF5OiBnZXRBcHBsZVBheVN0YXRlLFxuICAgIHByaXZhdGVDbGlja01lYXN1cmVtZW50OiBnZXRQcml2YXRlQ2xpY2tNZWFzdXJlbWVudCxcbiAgICBhdWRpb0Jhc2VMYXRlbmN5OiBnZXRBdWRpb0NvbnRleHRCYXNlTGF0ZW5jeSxcbiAgICBkYXRlVGltZUxvY2FsZTogZ2V0RGF0ZVRpbWVMb2NhbGUsXG4gICAgLy8gU29tZSBzb3VyY2VzIGNhbiBhZmZlY3Qgb3RoZXIgc291cmNlcyAoZS5nLiBXZWJHTCBjYW4gYWZmZWN0IGNhbnZhcyksIHNvIGl0J3MgaW1wb3J0YW50IHRvIHJ1biB0aGVzZSBzb3VyY2VzXG4gICAgLy8gYWZ0ZXIgb3RoZXIgc291cmNlcy5cbiAgICB3ZWJHbEJhc2ljczogZ2V0V2ViR2xCYXNpY3MsXG4gICAgd2ViR2xFeHRlbnNpb25zOiBnZXRXZWJHbEV4dGVuc2lvbnMsXG59O1xuLyoqXG4gKiBMb2FkcyB0aGUgYnVpbHQtaW4gZW50cm9weSBzb3VyY2VzLlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgY29sbGVjdHMgdGhlIGVudHJvcHkgY29tcG9uZW50cyB0byBtYWtlIHRoZSB2aXNpdG9yIGlkZW50aWZpZXIuXG4gKi9cbmZ1bmN0aW9uIGxvYWRCdWlsdGluU291cmNlcyhvcHRpb25zKSB7XG4gICAgcmV0dXJuIGxvYWRTb3VyY2VzKHNvdXJjZXMsIG9wdGlvbnMsIFtdKTtcbn1cblxuY29uc3QgY29tbWVudFRlbXBsYXRlID0gJyQgaWYgdXBncmFkZSB0byBQcm86IGh0dHBzOi8vZnBqcy5kZXYvcHJvJztcbmZ1bmN0aW9uIGdldENvbmZpZGVuY2UoY29tcG9uZW50cykge1xuICAgIGNvbnN0IG9wZW5Db25maWRlbmNlU2NvcmUgPSBnZXRPcGVuQ29uZmlkZW5jZVNjb3JlKGNvbXBvbmVudHMpO1xuICAgIGNvbnN0IHByb0NvbmZpZGVuY2VTY29yZSA9IGRlcml2ZVByb0NvbmZpZGVuY2VTY29yZShvcGVuQ29uZmlkZW5jZVNjb3JlKTtcbiAgICByZXR1cm4geyBzY29yZTogb3BlbkNvbmZpZGVuY2VTY29yZSwgY29tbWVudDogY29tbWVudFRlbXBsYXRlLnJlcGxhY2UoL1xcJC9nLCBgJHtwcm9Db25maWRlbmNlU2NvcmV9YCkgfTtcbn1cbmZ1bmN0aW9uIGdldE9wZW5Db25maWRlbmNlU2NvcmUoY29tcG9uZW50cykge1xuICAgIC8vIEluIG9yZGVyIHRvIGNhbGN1bGF0ZSB0aGUgdHJ1ZSBwcm9iYWJpbGl0eSBvZiB0aGUgdmlzaXRvciBpZGVudGlmaWVyIGJlaW5nIGNvcnJlY3QsIHdlIG5lZWQgdG8ga25vdyB0aGUgbnVtYmVyIG9mXG4gICAgLy8gd2Vic2l0ZSB2aXNpdG9ycyAodGhlIGhpZ2hlciB0aGUgbnVtYmVyLCB0aGUgbGVzcyB0aGUgcHJvYmFiaWxpdHkgYmVjYXVzZSB0aGUgZmluZ2VycHJpbnQgZW50cm9weSBpcyBsaW1pdGVkKS5cbiAgICAvLyBKUyBhZ2VudCBkb2Vzbid0IGtub3cgdGhlIG51bWJlciBvZiB2aXNpdG9ycywgc28gd2UgY2FuIG9ubHkgZG8gYW4gYXBwcm94aW1hdGUgYXNzZXNzbWVudC5cbiAgICBpZiAoaXNBbmRyb2lkKCkpIHtcbiAgICAgICAgcmV0dXJuIDAuNDtcbiAgICB9XG4gICAgLy8gU2FmYXJpIChtb2JpbGUgYW5kIGRlc2t0b3ApXG4gICAgaWYgKGlzV2ViS2l0KCkpIHtcbiAgICAgICAgcmV0dXJuIGlzRGVza3RvcFdlYktpdCgpICYmICEoaXNXZWJLaXQ2MTZPck5ld2VyKCkgJiYgaXNTYWZhcmlXZWJLaXQoKSkgPyAwLjUgOiAwLjM7XG4gICAgfVxuICAgIGNvbnN0IHBsYXRmb3JtID0gJ3ZhbHVlJyBpbiBjb21wb25lbnRzLnBsYXRmb3JtID8gY29tcG9uZW50cy5wbGF0Zm9ybS52YWx1ZSA6ICcnO1xuICAgIC8vIFdpbmRvd3NcbiAgICBpZiAoL15XaW4vLnRlc3QocGxhdGZvcm0pKSB7XG4gICAgICAgIC8vIFRoZSBzY29yZSBpcyBncmVhdGVyIHRoYW4gb24gbWFjT1MgYmVjYXVzZSBvZiB0aGUgaGlnaGVyIHZhcmlldHkgb2YgZGV2aWNlcyBydW5uaW5nIFdpbmRvd3MuXG4gICAgICAgIC8vIENocm9tZSBwcm92aWRlcyBtb3JlIGVudHJvcHkgdGhhbiBGaXJlZm94IGFjY29yZGluZyB0b29cbiAgICAgICAgLy8gaHR0cHM6Ly9uZXRtYXJrZXRzaGFyZS5jb20vYnJvd3Nlci1tYXJrZXQtc2hhcmUuYXNweD9vcHRpb25zPSU3QiUyMmZpbHRlciUyMiUzQSU3QiUyMiUyNGFuZCUyMiUzQSU1QiU3QiUyMnBsYXRmb3JtJTIyJTNBJTdCJTIyJTI0aW4lMjIlM0ElNUIlMjJXaW5kb3dzJTIyJTVEJTdEJTdEJTVEJTdEJTJDJTIyZGF0ZUxhYmVsJTIyJTNBJTIyVHJlbmQlMjIlMkMlMjJhdHRyaWJ1dGVzJTIyJTNBJTIyc2hhcmUlMjIlMkMlMjJncm91cCUyMiUzQSUyMmJyb3dzZXIlMjIlMkMlMjJzb3J0JTIyJTNBJTdCJTIyc2hhcmUlMjIlM0EtMSU3RCUyQyUyMmlkJTIyJTNBJTIyYnJvd3NlcnNEZXNrdG9wJTIyJTJDJTIyZGF0ZUludGVydmFsJTIyJTNBJTIyTW9udGhseSUyMiUyQyUyMmRhdGVTdGFydCUyMiUzQSUyMjIwMTktMTElMjIlMkMlMjJkYXRlRW5kJTIyJTNBJTIyMjAyMC0xMCUyMiUyQyUyMnNlZ21lbnRzJTIyJTNBJTIyLTEwMDAlMjIlN0RcbiAgICAgICAgLy8gU28gd2UgYXNzaWduIHRoZSBzYW1lIHNjb3JlIHRvIHRoZW0uXG4gICAgICAgIHJldHVybiAwLjY7XG4gICAgfVxuICAgIC8vIG1hY09TXG4gICAgaWYgKC9eTWFjLy50ZXN0KHBsYXRmb3JtKSkge1xuICAgICAgICAvLyBDaHJvbWUgcHJvdmlkZXMgbW9yZSBlbnRyb3B5IHRoYW4gU2FmYXJpIGFuZCBTYWZhcmkgcHJvdmlkZXMgbW9yZSBlbnRyb3B5IHRoYW4gRmlyZWZveC5cbiAgICAgICAgLy8gQ2hyb21lIGlzIG1vcmUgcG9wdWxhciB0aGFuIFNhZmFyaSBhbmQgU2FmYXJpIGlzIG1vcmUgcG9wdWxhciB0aGFuIEZpcmVmb3ggYWNjb3JkaW5nIHRvXG4gICAgICAgIC8vIGh0dHBzOi8vbmV0bWFya2V0c2hhcmUuY29tL2Jyb3dzZXItbWFya2V0LXNoYXJlLmFzcHg/b3B0aW9ucz0lN0IlMjJmaWx0ZXIlMjIlM0ElN0IlMjIlMjRhbmQlMjIlM0ElNUIlN0IlMjJwbGF0Zm9ybSUyMiUzQSU3QiUyMiUyNGluJTIyJTNBJTVCJTIyTWFjJTIwT1MlMjIlNUQlN0QlN0QlNUQlN0QlMkMlMjJkYXRlTGFiZWwlMjIlM0ElMjJUcmVuZCUyMiUyQyUyMmF0dHJpYnV0ZXMlMjIlM0ElMjJzaGFyZSUyMiUyQyUyMmdyb3VwJTIyJTNBJTIyYnJvd3NlciUyMiUyQyUyMnNvcnQlMjIlM0ElN0IlMjJzaGFyZSUyMiUzQS0xJTdEJTJDJTIyaWQlMjIlM0ElMjJicm93c2Vyc0Rlc2t0b3AlMjIlMkMlMjJkYXRlSW50ZXJ2YWwlMjIlM0ElMjJNb250aGx5JTIyJTJDJTIyZGF0ZVN0YXJ0JTIyJTNBJTIyMjAxOS0xMSUyMiUyQyUyMmRhdGVFbmQlMjIlM0ElMjIyMDIwLTEwJTIyJTJDJTIyc2VnbWVudHMlMjIlM0ElMjItMTAwMCUyMiU3RFxuICAgICAgICAvLyBTbyB3ZSBhc3NpZ24gdGhlIHNhbWUgc2NvcmUgdG8gdGhlbS5cbiAgICAgICAgcmV0dXJuIDAuNTtcbiAgICB9XG4gICAgLy8gQW5vdGhlciBwbGF0Zm9ybSwgZS5nLiBhIGRlc2t0b3AgTGludXguIEl0J3MgcmFyZSwgc28gaXQgc2hvdWxkIGJlIHByZXR0eSB1bmlxdWUuXG4gICAgcmV0dXJuIDAuNztcbn1cbmZ1bmN0aW9uIGRlcml2ZVByb0NvbmZpZGVuY2VTY29yZShvcGVuQ29uZmlkZW5jZVNjb3JlKSB7XG4gICAgcmV0dXJuIHJvdW5kKDAuOTkgKyAwLjAxICogb3BlbkNvbmZpZGVuY2VTY29yZSwgMC4wMDAxKTtcbn1cblxuZnVuY3Rpb24gY29tcG9uZW50c1RvQ2Fub25pY2FsU3RyaW5nKGNvbXBvbmVudHMpIHtcbiAgICBsZXQgcmVzdWx0ID0gJyc7XG4gICAgZm9yIChjb25zdCBjb21wb25lbnRLZXkgb2YgT2JqZWN0LmtleXMoY29tcG9uZW50cykuc29ydCgpKSB7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudCA9IGNvbXBvbmVudHNbY29tcG9uZW50S2V5XTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSAnZXJyb3InIGluIGNvbXBvbmVudCA/ICdlcnJvcicgOiBKU09OLnN0cmluZ2lmeShjb21wb25lbnQudmFsdWUpO1xuICAgICAgICByZXN1bHQgKz0gYCR7cmVzdWx0ID8gJ3wnIDogJyd9JHtjb21wb25lbnRLZXkucmVwbGFjZSgvKFs6fFxcXFxdKS9nLCAnXFxcXCQxJyl9OiR7dmFsdWV9YDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGNvbXBvbmVudHNUb0RlYnVnU3RyaW5nKGNvbXBvbmVudHMpIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoY29tcG9uZW50cywgKF9rZXksIHZhbHVlKSA9PiB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZXJyb3JUb09iamVjdCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sIDIpO1xufVxuZnVuY3Rpb24gaGFzaENvbXBvbmVudHMoY29tcG9uZW50cykge1xuICAgIHJldHVybiB4NjRoYXNoMTI4KGNvbXBvbmVudHNUb0Nhbm9uaWNhbFN0cmluZyhjb21wb25lbnRzKSk7XG59XG4vKipcbiAqIE1ha2VzIGEgR2V0UmVzdWx0IGltcGxlbWVudGF0aW9uIHRoYXQgY2FsY3VsYXRlcyB0aGUgdmlzaXRvciBpZCBoYXNoIG9uIGRlbWFuZC5cbiAqIERlc2lnbmVkIGZvciBvcHRpbWlzYXRpb24uXG4gKi9cbmZ1bmN0aW9uIG1ha2VMYXp5R2V0UmVzdWx0KGNvbXBvbmVudHMpIHtcbiAgICBsZXQgdmlzaXRvcklkQ2FjaGU7XG4gICAgLy8gVGhpcyBmdW5jdGlvbiBydW5zIHZlcnkgZmFzdCwgc28gdGhlcmUgaXMgbm8gbmVlZCB0byBtYWtlIGl0IGxhenlcbiAgICBjb25zdCBjb25maWRlbmNlID0gZ2V0Q29uZmlkZW5jZShjb21wb25lbnRzKTtcbiAgICAvLyBBIHBsYWluIGNsYXNzIGlzbid0IHVzZWQgYmVjYXVzZSBpdHMgZ2V0dGVycyBhbmQgc2V0dGVycyBhcmVuJ3QgZW51bWVyYWJsZS5cbiAgICByZXR1cm4ge1xuICAgICAgICBnZXQgdmlzaXRvcklkKCkge1xuICAgICAgICAgICAgaWYgKHZpc2l0b3JJZENhY2hlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB2aXNpdG9ySWRDYWNoZSA9IGhhc2hDb21wb25lbnRzKHRoaXMuY29tcG9uZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdmlzaXRvcklkQ2FjaGU7XG4gICAgICAgIH0sXG4gICAgICAgIHNldCB2aXNpdG9ySWQodmlzaXRvcklkKSB7XG4gICAgICAgICAgICB2aXNpdG9ySWRDYWNoZSA9IHZpc2l0b3JJZDtcbiAgICAgICAgfSxcbiAgICAgICAgY29uZmlkZW5jZSxcbiAgICAgICAgY29tcG9uZW50cyxcbiAgICAgICAgdmVyc2lvbixcbiAgICB9O1xufVxuLyoqXG4gKiBBIGRlbGF5IGlzIHJlcXVpcmVkIHRvIGVuc3VyZSBjb25zaXN0ZW50IGVudHJvcHkgY29tcG9uZW50cy5cbiAqIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2lzc3Vlcy8yNTRcbiAqIGFuZCBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2lzc3Vlcy8zMDdcbiAqIGFuZCBodHRwczovL2dpdGh1Yi5jb20vZmluZ2VycHJpbnRqcy9maW5nZXJwcmludGpzL2NvbW1pdC85NDU2MzNlN2M1ZjY3YWUzOGViMGZlYTM3MzQ5NzEyZjBlNjY5YjE4XG4gKi9cbmZ1bmN0aW9uIHByZXBhcmVGb3JTb3VyY2VzKGRlbGF5RmFsbGJhY2sgPSA1MCkge1xuICAgIC8vIEEgcHJvcGVyIGRlYWRsaW5lIGlzIHVua25vd24uIExldCBpdCBiZSB0d2ljZSB0aGUgZmFsbGJhY2sgdGltZW91dCBzbyB0aGF0IGJvdGggY2FzZXMgaGF2ZSB0aGUgc2FtZSBhdmVyYWdlIHRpbWUuXG4gICAgcmV0dXJuIHJlcXVlc3RJZGxlQ2FsbGJhY2tJZkF2YWlsYWJsZShkZWxheUZhbGxiYWNrLCBkZWxheUZhbGxiYWNrICogMik7XG59XG4vKipcbiAqIFRoZSBmdW5jdGlvbiBpc24ndCBleHBvcnRlZCBmcm9tIHRoZSBpbmRleCBmaWxlIHRvIG5vdCBhbGxvdyB0byBjYWxsIGl0IHdpdGhvdXQgYGxvYWQoKWAuXG4gKiBUaGUgaGlkaW5nIGdpdmVzIG1vcmUgZnJlZWRvbSBmb3IgZnV0dXJlIG5vbi1icmVha2luZyB1cGRhdGVzLlxuICpcbiAqIEEgZmFjdG9yeSBmdW5jdGlvbiBpcyB1c2VkIGluc3RlYWQgb2YgYSBjbGFzcyB0byBzaG9ydGVuIHRoZSBhdHRyaWJ1dGUgbmFtZXMgaW4gdGhlIG1pbmlmaWVkIGNvZGUuXG4gKiBOYXRpdmUgcHJpdmF0ZSBjbGFzcyBmaWVsZHMgY291bGQndmUgYmVlbiB1c2VkLCBidXQgVHlwZVNjcmlwdCBkb2Vzbid0IGFsbG93IHRoZW0gd2l0aCBgXCJ0YXJnZXRcIjogXCJlczVcImAuXG4gKi9cbmZ1bmN0aW9uIG1ha2VBZ2VudChnZXRDb21wb25lbnRzLCBkZWJ1Zykge1xuICAgIGNvbnN0IGNyZWF0aW9uVGltZSA9IERhdGUubm93KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYXN5bmMgZ2V0KG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBjb25zdCBjb21wb25lbnRzID0gYXdhaXQgZ2V0Q29tcG9uZW50cygpO1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gbWFrZUxhenlHZXRSZXN1bHQoY29tcG9uZW50cyk7XG4gICAgICAgICAgICBpZiAoZGVidWcgfHwgKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5kZWJ1ZykpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyBpcyBvayBoZXJlIGJlY2F1c2UgaXQncyB1bmRlciBhIGRlYnVnIGNsYXVzZVxuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coYENvcHkgdGhlIHRleHQgYmVsb3cgdG8gZ2V0IHRoZSBkZWJ1ZyBkYXRhOlxuXG5cXGBcXGBcXGBcbnZlcnNpb246ICR7cmVzdWx0LnZlcnNpb259XG51c2VyQWdlbnQ6ICR7bmF2aWdhdG9yLnVzZXJBZ2VudH1cbnRpbWVCZXR3ZWVuTG9hZEFuZEdldDogJHtzdGFydFRpbWUgLSBjcmVhdGlvblRpbWV9XG52aXNpdG9ySWQ6ICR7cmVzdWx0LnZpc2l0b3JJZH1cbmNvbXBvbmVudHM6ICR7Y29tcG9uZW50c1RvRGVidWdTdHJpbmcoY29tcG9uZW50cyl9XG5cXGBcXGBcXGBgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbi8qKlxuICogU2VuZHMgYW4gdW5wZXJzb25hbGl6ZWQgQUpBWCByZXF1ZXN0IHRvIGNvbGxlY3QgaW5zdGFsbGF0aW9uIHN0YXRpc3RpY3NcbiAqL1xuZnVuY3Rpb24gbW9uaXRvcigpIHtcbiAgICAvLyBUaGUgRmluZ2VycHJpbnRKUyBDRE4gKGh0dHBzOi8vZ2l0aHViLmNvbS9maW5nZXJwcmludGpzL2NkbikgcmVwbGFjZXMgYHdpbmRvdy5fX2ZwanNfZF9tYCB3aXRoIGB0cnVlYFxuICAgIGlmICh3aW5kb3cuX19mcGpzX2RfbSB8fCBNYXRoLnJhbmRvbSgpID49IDAuMDAxKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICByZXF1ZXN0Lm9wZW4oJ2dldCcsIGBodHRwczovL20xLm9wZW5mcGNkbi5pby9maW5nZXJwcmludGpzL3Yke3ZlcnNpb259L25wbS1tb25pdG9yaW5nYCwgdHJ1ZSk7XG4gICAgICAgIHJlcXVlc3Quc2VuZCgpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gY29uc29sZS5lcnJvciBpcyBvayBoZXJlIGJlY2F1c2UgaXQncyBhbiB1bmV4cGVjdGVkIGVycm9yIGhhbmRsZXJcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxufVxuLyoqXG4gKiBCdWlsZHMgYW4gaW5zdGFuY2Ugb2YgQWdlbnQgYW5kIHdhaXRzIGEgZGVsYXkgcmVxdWlyZWQgZm9yIGEgcHJvcGVyIG9wZXJhdGlvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbG9hZChvcHRpb25zID0ge30pIHtcbiAgICB2YXIgX2E7XG4gICAgaWYgKChfYSA9IG9wdGlvbnMubW9uaXRvcmluZykgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogdHJ1ZSkge1xuICAgICAgICBtb25pdG9yKCk7XG4gICAgfVxuICAgIGNvbnN0IHsgZGVsYXlGYWxsYmFjaywgZGVidWcgfSA9IG9wdGlvbnM7XG4gICAgYXdhaXQgcHJlcGFyZUZvclNvdXJjZXMoZGVsYXlGYWxsYmFjayk7XG4gICAgY29uc3QgZ2V0Q29tcG9uZW50cyA9IGxvYWRCdWlsdGluU291cmNlcyh7IGNhY2hlOiB7fSwgZGVidWcgfSk7XG4gICAgcmV0dXJuIG1ha2VBZ2VudChnZXRDb21wb25lbnRzLCBkZWJ1Zyk7XG59XG5cbi8vIFRoZSBkZWZhdWx0IGV4cG9ydCBpcyBhIHN5bnRheCBzdWdhciAoYGltcG9ydCAqIGFzIEZQIGZyb20gJy4uLicgXHUyMTkyIGltcG9ydCBGUCBmcm9tICcuLi4nYCkuXG4vLyBJdCBzaG91bGQgY29udGFpbiBhbGwgdGhlIHB1YmxpYyBleHBvcnRlZCB2YWx1ZXMuXG52YXIgaW5kZXggPSB7IGxvYWQsIGhhc2hDb21wb25lbnRzLCBjb21wb25lbnRzVG9EZWJ1Z1N0cmluZyB9O1xuLy8gVGhlIGV4cG9ydHMgYmVsb3cgYXJlIGZvciBwcml2YXRlIHVzYWdlLiBUaGV5IG1heSBjaGFuZ2UgdW5leHBlY3RlZGx5LiBVc2UgdGhlbSBhdCB5b3VyIG93biByaXNrLlxuLyoqIE5vdCBkb2N1bWVudGVkLCBvdXQgb2YgU2VtYW50aWMgVmVyc2lvbmluZywgdXNhZ2UgaXMgYXQgeW91ciBvd24gcmlzayAqL1xuY29uc3QgbXVybXVyWDY0SGFzaDEyOCA9IHg2NGhhc2gxMjg7XG5cbmV4cG9ydHMuY29tcG9uZW50c1RvRGVidWdTdHJpbmcgPSBjb21wb25lbnRzVG9EZWJ1Z1N0cmluZztcbmV4cG9ydHMuZGVmYXVsdCA9IGluZGV4O1xuZXhwb3J0cy5nZXRGdWxsc2NyZWVuRWxlbWVudCA9IGdldEZ1bGxzY3JlZW5FbGVtZW50O1xuZXhwb3J0cy5nZXRVbnN0YWJsZUF1ZGlvRmluZ2VycHJpbnQgPSBnZXRVbnN0YWJsZUF1ZGlvRmluZ2VycHJpbnQ7XG5leHBvcnRzLmdldFVuc3RhYmxlQ2FudmFzRmluZ2VycHJpbnQgPSBnZXRVbnN0YWJsZUNhbnZhc0ZpbmdlcnByaW50O1xuZXhwb3J0cy5nZXRVbnN0YWJsZVNjcmVlbkZyYW1lID0gZ2V0VW5zdGFibGVTY3JlZW5GcmFtZTtcbmV4cG9ydHMuZ2V0VW5zdGFibGVTY3JlZW5SZXNvbHV0aW9uID0gZ2V0VW5zdGFibGVTY3JlZW5SZXNvbHV0aW9uO1xuZXhwb3J0cy5nZXRXZWJHTENvbnRleHQgPSBnZXRXZWJHTENvbnRleHQ7XG5leHBvcnRzLmhhc2hDb21wb25lbnRzID0gaGFzaENvbXBvbmVudHM7XG5leHBvcnRzLmlzQW5kcm9pZCA9IGlzQW5kcm9pZDtcbmV4cG9ydHMuaXNDaHJvbWl1bSA9IGlzQ2hyb21pdW07XG5leHBvcnRzLmlzRGVza3RvcFdlYktpdCA9IGlzRGVza3RvcFdlYktpdDtcbmV4cG9ydHMuaXNFZGdlSFRNTCA9IGlzRWRnZUhUTUw7XG5leHBvcnRzLmlzR2Vja28gPSBpc0dlY2tvO1xuZXhwb3J0cy5pc1NhbXN1bmdJbnRlcm5ldCA9IGlzU2Ftc3VuZ0ludGVybmV0O1xuZXhwb3J0cy5pc1RyaWRlbnQgPSBpc1RyaWRlbnQ7XG5leHBvcnRzLmlzV2ViS2l0ID0gaXNXZWJLaXQ7XG5leHBvcnRzLmxvYWQgPSBsb2FkO1xuZXhwb3J0cy5sb2FkU291cmNlcyA9IGxvYWRTb3VyY2VzO1xuZXhwb3J0cy5tdXJtdXJYNjRIYXNoMTI4ID0gbXVybXVyWDY0SGFzaDEyODtcbmV4cG9ydHMucHJlcGFyZUZvclNvdXJjZXMgPSBwcmVwYXJlRm9yU291cmNlcztcbmV4cG9ydHMuc291cmNlcyA9IHNvdXJjZXM7XG5leHBvcnRzLnRyYW5zZm9ybVNvdXJjZSA9IHRyYW5zZm9ybVNvdXJjZTtcbmV4cG9ydHMud2l0aElmcmFtZSA9IHdpdGhJZnJhbWU7XG4iLCAiJ3VzZSBzdHJpY3QnO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbmV4cG9ydHMuZ2V0RGVmYXVsdHNGcm9tUG9zdGluc3RhbGwgPSAoKSA9PiAodW5kZWZpbmVkKTsiLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IEZpcmViYXNlIGNvbnN0YW50cy4gIFNvbWUgb2YgdGhlc2UgKEBkZWZpbmVzKSBjYW4gYmUgb3ZlcnJpZGRlbiBhdCBjb21waWxlLXRpbWUuXG4gKi9cblxuZXhwb3J0IGNvbnN0IENPTlNUQU5UUyA9IHtcbiAgLyoqXG4gICAqIEBkZWZpbmUge2Jvb2xlYW59IFdoZXRoZXIgdGhpcyBpcyB0aGUgY2xpZW50IE5vZGUuanMgU0RLLlxuICAgKi9cbiAgTk9ERV9DTElFTlQ6IGZhbHNlLFxuICAvKipcbiAgICogQGRlZmluZSB7Ym9vbGVhbn0gV2hldGhlciB0aGlzIGlzIHRoZSBBZG1pbiBOb2RlLmpzIFNESy5cbiAgICovXG4gIE5PREVfQURNSU46IGZhbHNlLFxuXG4gIC8qKlxuICAgKiBGaXJlYmFzZSBTREsgVmVyc2lvblxuICAgKi9cbiAgU0RLX1ZFUlNJT046ICcke0pTQ09SRV9WRVJTSU9OfSdcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQ09OU1RBTlRTIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuXG4vKipcbiAqIFRocm93cyBhbiBlcnJvciBpZiB0aGUgcHJvdmlkZWQgYXNzZXJ0aW9uIGlzIGZhbHN5XG4gKi9cbmV4cG9ydCBjb25zdCBhc3NlcnQgPSBmdW5jdGlvbiAoYXNzZXJ0aW9uOiB1bmtub3duLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCFhc3NlcnRpb24pIHtcbiAgICB0aHJvdyBhc3NlcnRpb25FcnJvcihtZXNzYWdlKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXR1cm5zIGFuIEVycm9yIG9iamVjdCBzdWl0YWJsZSBmb3IgdGhyb3dpbmcuXG4gKi9cbmV4cG9ydCBjb25zdCBhc3NlcnRpb25FcnJvciA9IGZ1bmN0aW9uIChtZXNzYWdlOiBzdHJpbmcpOiBFcnJvciB7XG4gIHJldHVybiBuZXcgRXJyb3IoXG4gICAgJ0ZpcmViYXNlIERhdGFiYXNlICgnICtcbiAgICAgIENPTlNUQU5UUy5TREtfVkVSU0lPTiArXG4gICAgICAnKSBJTlRFUk5BTCBBU1NFUlQgRkFJTEVEOiAnICtcbiAgICAgIG1lc3NhZ2VcbiAgKTtcbn07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuY29uc3Qgc3RyaW5nVG9CeXRlQXJyYXkgPSBmdW5jdGlvbiAoc3RyOiBzdHJpbmcpOiBudW1iZXJbXSB7XG4gIC8vIFRPRE8odXNlcik6IFVzZSBuYXRpdmUgaW1wbGVtZW50YXRpb25zIGlmL3doZW4gYXZhaWxhYmxlXG4gIGNvbnN0IG91dDogbnVtYmVyW10gPSBbXTtcbiAgbGV0IHAgPSAwO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgIG91dFtwKytdID0gYztcbiAgICB9IGVsc2UgaWYgKGMgPCAyMDQ4KSB7XG4gICAgICBvdXRbcCsrXSA9IChjID4+IDYpIHwgMTkyO1xuICAgICAgb3V0W3ArK10gPSAoYyAmIDYzKSB8IDEyODtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgKGMgJiAweGZjMDApID09PSAweGQ4MDAgJiZcbiAgICAgIGkgKyAxIDwgc3RyLmxlbmd0aCAmJlxuICAgICAgKHN0ci5jaGFyQ29kZUF0KGkgKyAxKSAmIDB4ZmMwMCkgPT09IDB4ZGMwMFxuICAgICkge1xuICAgICAgLy8gU3Vycm9nYXRlIFBhaXJcbiAgICAgIGMgPSAweDEwMDAwICsgKChjICYgMHgwM2ZmKSA8PCAxMCkgKyAoc3RyLmNoYXJDb2RlQXQoKytpKSAmIDB4MDNmZik7XG4gICAgICBvdXRbcCsrXSA9IChjID4+IDE4KSB8IDI0MDtcbiAgICAgIG91dFtwKytdID0gKChjID4+IDEyKSAmIDYzKSB8IDEyODtcbiAgICAgIG91dFtwKytdID0gKChjID4+IDYpICYgNjMpIHwgMTI4O1xuICAgICAgb3V0W3ArK10gPSAoYyAmIDYzKSB8IDEyODtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0W3ArK10gPSAoYyA+PiAxMikgfCAyMjQ7XG4gICAgICBvdXRbcCsrXSA9ICgoYyA+PiA2KSAmIDYzKSB8IDEyODtcbiAgICAgIG91dFtwKytdID0gKGMgJiA2MykgfCAxMjg7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIFR1cm5zIGFuIGFycmF5IG9mIG51bWJlcnMgaW50byB0aGUgc3RyaW5nIGdpdmVuIGJ5IHRoZSBjb25jYXRlbmF0aW9uIG9mIHRoZVxuICogY2hhcmFjdGVycyB0byB3aGljaCB0aGUgbnVtYmVycyBjb3JyZXNwb25kLlxuICogQHBhcmFtIGJ5dGVzIEFycmF5IG9mIG51bWJlcnMgcmVwcmVzZW50aW5nIGNoYXJhY3RlcnMuXG4gKiBAcmV0dXJuIFN0cmluZ2lmaWNhdGlvbiBvZiB0aGUgYXJyYXkuXG4gKi9cbmNvbnN0IGJ5dGVBcnJheVRvU3RyaW5nID0gZnVuY3Rpb24gKGJ5dGVzOiBudW1iZXJbXSk6IHN0cmluZyB7XG4gIC8vIFRPRE8odXNlcik6IFVzZSBuYXRpdmUgaW1wbGVtZW50YXRpb25zIGlmL3doZW4gYXZhaWxhYmxlXG4gIGNvbnN0IG91dDogc3RyaW5nW10gPSBbXTtcbiAgbGV0IHBvcyA9IDAsXG4gICAgYyA9IDA7XG4gIHdoaWxlIChwb3MgPCBieXRlcy5sZW5ndGgpIHtcbiAgICBjb25zdCBjMSA9IGJ5dGVzW3BvcysrXTtcbiAgICBpZiAoYzEgPCAxMjgpIHtcbiAgICAgIG91dFtjKytdID0gU3RyaW5nLmZyb21DaGFyQ29kZShjMSk7XG4gICAgfSBlbHNlIGlmIChjMSA+IDE5MSAmJiBjMSA8IDIyNCkge1xuICAgICAgY29uc3QgYzIgPSBieXRlc1twb3MrK107XG4gICAgICBvdXRbYysrXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoKChjMSAmIDMxKSA8PCA2KSB8IChjMiAmIDYzKSk7XG4gICAgfSBlbHNlIGlmIChjMSA+IDIzOSAmJiBjMSA8IDM2NSkge1xuICAgICAgLy8gU3Vycm9nYXRlIFBhaXJcbiAgICAgIGNvbnN0IGMyID0gYnl0ZXNbcG9zKytdO1xuICAgICAgY29uc3QgYzMgPSBieXRlc1twb3MrK107XG4gICAgICBjb25zdCBjNCA9IGJ5dGVzW3BvcysrXTtcbiAgICAgIGNvbnN0IHUgPVxuICAgICAgICAoKChjMSAmIDcpIDw8IDE4KSB8ICgoYzIgJiA2MykgPDwgMTIpIHwgKChjMyAmIDYzKSA8PCA2KSB8IChjNCAmIDYzKSkgLVxuICAgICAgICAweDEwMDAwO1xuICAgICAgb3V0W2MrK10gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4ZDgwMCArICh1ID4+IDEwKSk7XG4gICAgICBvdXRbYysrXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhkYzAwICsgKHUgJiAxMDIzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGMyID0gYnl0ZXNbcG9zKytdO1xuICAgICAgY29uc3QgYzMgPSBieXRlc1twb3MrK107XG4gICAgICBvdXRbYysrXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICAgICgoYzEgJiAxNSkgPDwgMTIpIHwgKChjMiAmIDYzKSA8PCA2KSB8IChjMyAmIDYzKVxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dC5qb2luKCcnKTtcbn07XG5cbmludGVyZmFjZSBCYXNlNjQge1xuICBieXRlVG9DaGFyTWFwXzogeyBba2V5OiBudW1iZXJdOiBzdHJpbmcgfSB8IG51bGw7XG4gIGNoYXJUb0J5dGVNYXBfOiB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9IHwgbnVsbDtcbiAgYnl0ZVRvQ2hhck1hcFdlYlNhZmVfOiB7IFtrZXk6IG51bWJlcl06IHN0cmluZyB9IHwgbnVsbDtcbiAgY2hhclRvQnl0ZU1hcFdlYlNhZmVfOiB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9IHwgbnVsbDtcbiAgRU5DT0RFRF9WQUxTX0JBU0U6IHN0cmluZztcbiAgcmVhZG9ubHkgRU5DT0RFRF9WQUxTOiBzdHJpbmc7XG4gIHJlYWRvbmx5IEVOQ09ERURfVkFMU19XRUJTQUZFOiBzdHJpbmc7XG4gIEhBU19OQVRJVkVfU1VQUE9SVDogYm9vbGVhbjtcbiAgZW5jb2RlQnl0ZUFycmF5KGlucHV0OiBudW1iZXJbXSB8IFVpbnQ4QXJyYXksIHdlYlNhZmU/OiBib29sZWFuKTogc3RyaW5nO1xuICBlbmNvZGVTdHJpbmcoaW5wdXQ6IHN0cmluZywgd2ViU2FmZT86IGJvb2xlYW4pOiBzdHJpbmc7XG4gIGRlY29kZVN0cmluZyhpbnB1dDogc3RyaW5nLCB3ZWJTYWZlOiBib29sZWFuKTogc3RyaW5nO1xuICBkZWNvZGVTdHJpbmdUb0J5dGVBcnJheShpbnB1dDogc3RyaW5nLCB3ZWJTYWZlOiBib29sZWFuKTogbnVtYmVyW107XG4gIGluaXRfKCk6IHZvaWQ7XG59XG5cbi8vIFdlIGRlZmluZSBpdCBhcyBhbiBvYmplY3QgbGl0ZXJhbCBpbnN0ZWFkIG9mIGEgY2xhc3MgYmVjYXVzZSBhIGNsYXNzIGNvbXBpbGVkIGRvd24gdG8gZXM1IGNhbid0XG4vLyBiZSB0cmVlc2hha2VkLiBodHRwczovL2dpdGh1Yi5jb20vcm9sbHVwL3JvbGx1cC9pc3N1ZXMvMTY5MVxuLy8gU3RhdGljIGxvb2t1cCBtYXBzLCBsYXppbHkgcG9wdWxhdGVkIGJ5IGluaXRfKClcbi8vIFRPRE8oZGxhcm9jcXVlKTogRGVmaW5lIHRoaXMgYXMgYSBjbGFzcywgc2luY2Ugd2Ugbm8gbG9uZ2VyIHRhcmdldCBFUzUuXG5leHBvcnQgY29uc3QgYmFzZTY0OiBCYXNlNjQgPSB7XG4gIC8qKlxuICAgKiBNYXBzIGJ5dGVzIHRvIGNoYXJhY3RlcnMuXG4gICAqL1xuICBieXRlVG9DaGFyTWFwXzogbnVsbCxcblxuICAvKipcbiAgICogTWFwcyBjaGFyYWN0ZXJzIHRvIGJ5dGVzLlxuICAgKi9cbiAgY2hhclRvQnl0ZU1hcF86IG51bGwsXG5cbiAgLyoqXG4gICAqIE1hcHMgYnl0ZXMgdG8gd2Vic2FmZSBjaGFyYWN0ZXJzLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgYnl0ZVRvQ2hhck1hcFdlYlNhZmVfOiBudWxsLFxuXG4gIC8qKlxuICAgKiBNYXBzIHdlYnNhZmUgY2hhcmFjdGVycyB0byBieXRlcy5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGNoYXJUb0J5dGVNYXBXZWJTYWZlXzogbnVsbCxcblxuICAvKipcbiAgICogT3VyIGRlZmF1bHQgYWxwaGFiZXQsIHNoYXJlZCBiZXR3ZWVuXG4gICAqIEVOQ09ERURfVkFMUyBhbmQgRU5DT0RFRF9WQUxTX1dFQlNBRkVcbiAgICovXG4gIEVOQ09ERURfVkFMU19CQVNFOlxuICAgICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWicgKyAnYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonICsgJzAxMjM0NTY3ODknLFxuXG4gIC8qKlxuICAgKiBPdXIgZGVmYXVsdCBhbHBoYWJldC4gVmFsdWUgNjQgKD0pIGlzIHNwZWNpYWw7IGl0IG1lYW5zIFwibm90aGluZy5cIlxuICAgKi9cbiAgZ2V0IEVOQ09ERURfVkFMUygpIHtcbiAgICByZXR1cm4gdGhpcy5FTkNPREVEX1ZBTFNfQkFTRSArICcrLz0nO1xuICB9LFxuXG4gIC8qKlxuICAgKiBPdXIgd2Vic2FmZSBhbHBoYWJldC5cbiAgICovXG4gIGdldCBFTkNPREVEX1ZBTFNfV0VCU0FGRSgpIHtcbiAgICByZXR1cm4gdGhpcy5FTkNPREVEX1ZBTFNfQkFTRSArICctXy4nO1xuICB9LFxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgYnJvd3NlciBzdXBwb3J0cyB0aGUgYXRvYiBhbmQgYnRvYSBmdW5jdGlvbnMuIFRoaXMgZXh0ZW5zaW9uXG4gICAqIHN0YXJ0ZWQgYXQgTW96aWxsYSBidXQgaXMgbm93IGltcGxlbWVudGVkIGJ5IG1hbnkgYnJvd3NlcnMuIFdlIHVzZSB0aGVcbiAgICogQVNTVU1FXyogdmFyaWFibGVzIHRvIGF2b2lkIHB1bGxpbmcgaW4gdGhlIGZ1bGwgdXNlcmFnZW50IGRldGVjdGlvbiBsaWJyYXJ5XG4gICAqIGJ1dCBzdGlsbCBhbGxvd2luZyB0aGUgc3RhbmRhcmQgcGVyLWJyb3dzZXIgY29tcGlsYXRpb25zLlxuICAgKlxuICAgKi9cbiAgSEFTX05BVElWRV9TVVBQT1JUOiB0eXBlb2YgYXRvYiA9PT0gJ2Z1bmN0aW9uJyxcblxuICAvKipcbiAgICogQmFzZTY0LWVuY29kZSBhbiBhcnJheSBvZiBieXRlcy5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IEFuIGFycmF5IG9mIGJ5dGVzIChudW1iZXJzIHdpdGhcbiAgICogICAgIHZhbHVlIGluIFswLCAyNTVdKSB0byBlbmNvZGUuXG4gICAqIEBwYXJhbSB3ZWJTYWZlIEJvb2xlYW4gaW5kaWNhdGluZyB3ZSBzaG91bGQgdXNlIHRoZVxuICAgKiAgICAgYWx0ZXJuYXRpdmUgYWxwaGFiZXQuXG4gICAqIEByZXR1cm4gVGhlIGJhc2U2NCBlbmNvZGVkIHN0cmluZy5cbiAgICovXG4gIGVuY29kZUJ5dGVBcnJheShpbnB1dDogbnVtYmVyW10gfCBVaW50OEFycmF5LCB3ZWJTYWZlPzogYm9vbGVhbik6IHN0cmluZyB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGlucHV0KSkge1xuICAgICAgdGhyb3cgRXJyb3IoJ2VuY29kZUJ5dGVBcnJheSB0YWtlcyBhbiBhcnJheSBhcyBhIHBhcmFtZXRlcicpO1xuICAgIH1cblxuICAgIHRoaXMuaW5pdF8oKTtcblxuICAgIGNvbnN0IGJ5dGVUb0NoYXJNYXAgPSB3ZWJTYWZlXG4gICAgICA/IHRoaXMuYnl0ZVRvQ2hhck1hcFdlYlNhZmVfIVxuICAgICAgOiB0aGlzLmJ5dGVUb0NoYXJNYXBfITtcblxuICAgIGNvbnN0IG91dHB1dCA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7IGkgKz0gMykge1xuICAgICAgY29uc3QgYnl0ZTEgPSBpbnB1dFtpXTtcbiAgICAgIGNvbnN0IGhhdmVCeXRlMiA9IGkgKyAxIDwgaW5wdXQubGVuZ3RoO1xuICAgICAgY29uc3QgYnl0ZTIgPSBoYXZlQnl0ZTIgPyBpbnB1dFtpICsgMV0gOiAwO1xuICAgICAgY29uc3QgaGF2ZUJ5dGUzID0gaSArIDIgPCBpbnB1dC5sZW5ndGg7XG4gICAgICBjb25zdCBieXRlMyA9IGhhdmVCeXRlMyA/IGlucHV0W2kgKyAyXSA6IDA7XG5cbiAgICAgIGNvbnN0IG91dEJ5dGUxID0gYnl0ZTEgPj4gMjtcbiAgICAgIGNvbnN0IG91dEJ5dGUyID0gKChieXRlMSAmIDB4MDMpIDw8IDQpIHwgKGJ5dGUyID4+IDQpO1xuICAgICAgbGV0IG91dEJ5dGUzID0gKChieXRlMiAmIDB4MGYpIDw8IDIpIHwgKGJ5dGUzID4+IDYpO1xuICAgICAgbGV0IG91dEJ5dGU0ID0gYnl0ZTMgJiAweDNmO1xuXG4gICAgICBpZiAoIWhhdmVCeXRlMykge1xuICAgICAgICBvdXRCeXRlNCA9IDY0O1xuXG4gICAgICAgIGlmICghaGF2ZUJ5dGUyKSB7XG4gICAgICAgICAgb3V0Qnl0ZTMgPSA2NDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvdXRwdXQucHVzaChcbiAgICAgICAgYnl0ZVRvQ2hhck1hcFtvdXRCeXRlMV0sXG4gICAgICAgIGJ5dGVUb0NoYXJNYXBbb3V0Qnl0ZTJdLFxuICAgICAgICBieXRlVG9DaGFyTWFwW291dEJ5dGUzXSxcbiAgICAgICAgYnl0ZVRvQ2hhck1hcFtvdXRCeXRlNF1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dC5qb2luKCcnKTtcbiAgfSxcblxuICAvKipcbiAgICogQmFzZTY0LWVuY29kZSBhIHN0cmluZy5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IEEgc3RyaW5nIHRvIGVuY29kZS5cbiAgICogQHBhcmFtIHdlYlNhZmUgSWYgdHJ1ZSwgd2Ugc2hvdWxkIHVzZSB0aGVcbiAgICogICAgIGFsdGVybmF0aXZlIGFscGhhYmV0LlxuICAgKiBAcmV0dXJuIFRoZSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcuXG4gICAqL1xuICBlbmNvZGVTdHJpbmcoaW5wdXQ6IHN0cmluZywgd2ViU2FmZT86IGJvb2xlYW4pOiBzdHJpbmcge1xuICAgIC8vIFNob3J0Y3V0IGZvciBNb3ppbGxhIGJyb3dzZXJzIHRoYXQgaW1wbGVtZW50XG4gICAgLy8gYSBuYXRpdmUgYmFzZTY0IGVuY29kZXIgaW4gdGhlIGZvcm0gb2YgXCJidG9hL2F0b2JcIlxuICAgIGlmICh0aGlzLkhBU19OQVRJVkVfU1VQUE9SVCAmJiAhd2ViU2FmZSkge1xuICAgICAgcmV0dXJuIGJ0b2EoaW5wdXQpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lbmNvZGVCeXRlQXJyYXkoc3RyaW5nVG9CeXRlQXJyYXkoaW5wdXQpLCB3ZWJTYWZlKTtcbiAgfSxcblxuICAvKipcbiAgICogQmFzZTY0LWRlY29kZSBhIHN0cmluZy5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IHRvIGRlY29kZS5cbiAgICogQHBhcmFtIHdlYlNhZmUgVHJ1ZSBpZiB3ZSBzaG91bGQgdXNlIHRoZVxuICAgKiAgICAgYWx0ZXJuYXRpdmUgYWxwaGFiZXQuXG4gICAqIEByZXR1cm4gc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgZGVjb2RlZCB2YWx1ZS5cbiAgICovXG4gIGRlY29kZVN0cmluZyhpbnB1dDogc3RyaW5nLCB3ZWJTYWZlOiBib29sZWFuKTogc3RyaW5nIHtcbiAgICAvLyBTaG9ydGN1dCBmb3IgTW96aWxsYSBicm93c2VycyB0aGF0IGltcGxlbWVudFxuICAgIC8vIGEgbmF0aXZlIGJhc2U2NCBlbmNvZGVyIGluIHRoZSBmb3JtIG9mIFwiYnRvYS9hdG9iXCJcbiAgICBpZiAodGhpcy5IQVNfTkFUSVZFX1NVUFBPUlQgJiYgIXdlYlNhZmUpIHtcbiAgICAgIHJldHVybiBhdG9iKGlucHV0KTtcbiAgICB9XG4gICAgcmV0dXJuIGJ5dGVBcnJheVRvU3RyaW5nKHRoaXMuZGVjb2RlU3RyaW5nVG9CeXRlQXJyYXkoaW5wdXQsIHdlYlNhZmUpKTtcbiAgfSxcblxuICAvKipcbiAgICogQmFzZTY0LWRlY29kZSBhIHN0cmluZy5cbiAgICpcbiAgICogSW4gYmFzZS02NCBkZWNvZGluZywgZ3JvdXBzIG9mIGZvdXIgY2hhcmFjdGVycyBhcmUgY29udmVydGVkIGludG8gdGhyZWVcbiAgICogYnl0ZXMuICBJZiB0aGUgZW5jb2RlciBkaWQgbm90IGFwcGx5IHBhZGRpbmcsIHRoZSBpbnB1dCBsZW5ndGggbWF5IG5vdFxuICAgKiBiZSBhIG11bHRpcGxlIG9mIDQuXG4gICAqXG4gICAqIEluIHRoaXMgY2FzZSwgdGhlIGxhc3QgZ3JvdXAgd2lsbCBoYXZlIGZld2VyIHRoYW4gNCBjaGFyYWN0ZXJzLCBhbmRcbiAgICogcGFkZGluZyB3aWxsIGJlIGluZmVycmVkLiAgSWYgdGhlIGdyb3VwIGhhcyBvbmUgb3IgdHdvIGNoYXJhY3RlcnMsIGl0IGRlY29kZXNcbiAgICogdG8gb25lIGJ5dGUuICBJZiB0aGUgZ3JvdXAgaGFzIHRocmVlIGNoYXJhY3RlcnMsIGl0IGRlY29kZXMgdG8gdHdvIGJ5dGVzLlxuICAgKlxuICAgKiBAcGFyYW0gaW5wdXQgSW5wdXQgdG8gZGVjb2RlLlxuICAgKiBAcGFyYW0gd2ViU2FmZSBUcnVlIGlmIHdlIHNob3VsZCB1c2UgdGhlIHdlYi1zYWZlIGFscGhhYmV0LlxuICAgKiBAcmV0dXJuIGJ5dGVzIHJlcHJlc2VudGluZyB0aGUgZGVjb2RlZCB2YWx1ZS5cbiAgICovXG4gIGRlY29kZVN0cmluZ1RvQnl0ZUFycmF5KGlucHV0OiBzdHJpbmcsIHdlYlNhZmU6IGJvb2xlYW4pOiBudW1iZXJbXSB7XG4gICAgdGhpcy5pbml0XygpO1xuXG4gICAgY29uc3QgY2hhclRvQnl0ZU1hcCA9IHdlYlNhZmVcbiAgICAgID8gdGhpcy5jaGFyVG9CeXRlTWFwV2ViU2FmZV8hXG4gICAgICA6IHRoaXMuY2hhclRvQnl0ZU1hcF8hO1xuXG4gICAgY29uc3Qgb3V0cHV0OiBudW1iZXJbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7ICkge1xuICAgICAgY29uc3QgYnl0ZTEgPSBjaGFyVG9CeXRlTWFwW2lucHV0LmNoYXJBdChpKyspXTtcblxuICAgICAgY29uc3QgaGF2ZUJ5dGUyID0gaSA8IGlucHV0Lmxlbmd0aDtcbiAgICAgIGNvbnN0IGJ5dGUyID0gaGF2ZUJ5dGUyID8gY2hhclRvQnl0ZU1hcFtpbnB1dC5jaGFyQXQoaSldIDogMDtcbiAgICAgICsraTtcblxuICAgICAgY29uc3QgaGF2ZUJ5dGUzID0gaSA8IGlucHV0Lmxlbmd0aDtcbiAgICAgIGNvbnN0IGJ5dGUzID0gaGF2ZUJ5dGUzID8gY2hhclRvQnl0ZU1hcFtpbnB1dC5jaGFyQXQoaSldIDogNjQ7XG4gICAgICArK2k7XG5cbiAgICAgIGNvbnN0IGhhdmVCeXRlNCA9IGkgPCBpbnB1dC5sZW5ndGg7XG4gICAgICBjb25zdCBieXRlNCA9IGhhdmVCeXRlNCA/IGNoYXJUb0J5dGVNYXBbaW5wdXQuY2hhckF0KGkpXSA6IDY0O1xuICAgICAgKytpO1xuXG4gICAgICBpZiAoYnl0ZTEgPT0gbnVsbCB8fCBieXRlMiA9PSBudWxsIHx8IGJ5dGUzID09IG51bGwgfHwgYnl0ZTQgPT0gbnVsbCkge1xuICAgICAgICB0aHJvdyBuZXcgRGVjb2RlQmFzZTY0U3RyaW5nRXJyb3IoKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3V0Qnl0ZTEgPSAoYnl0ZTEgPDwgMikgfCAoYnl0ZTIgPj4gNCk7XG4gICAgICBvdXRwdXQucHVzaChvdXRCeXRlMSk7XG5cbiAgICAgIGlmIChieXRlMyAhPT0gNjQpIHtcbiAgICAgICAgY29uc3Qgb3V0Qnl0ZTIgPSAoKGJ5dGUyIDw8IDQpICYgMHhmMCkgfCAoYnl0ZTMgPj4gMik7XG4gICAgICAgIG91dHB1dC5wdXNoKG91dEJ5dGUyKTtcblxuICAgICAgICBpZiAoYnl0ZTQgIT09IDY0KSB7XG4gICAgICAgICAgY29uc3Qgb3V0Qnl0ZTMgPSAoKGJ5dGUzIDw8IDYpICYgMHhjMCkgfCBieXRlNDtcbiAgICAgICAgICBvdXRwdXQucHVzaChvdXRCeXRlMyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9LFxuXG4gIC8qKlxuICAgKiBMYXp5IHN0YXRpYyBpbml0aWFsaXphdGlvbiBmdW5jdGlvbi4gQ2FsbGVkIGJlZm9yZVxuICAgKiBhY2Nlc3NpbmcgYW55IG9mIHRoZSBzdGF0aWMgbWFwIHZhcmlhYmxlcy5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIGluaXRfKCkge1xuICAgIGlmICghdGhpcy5ieXRlVG9DaGFyTWFwXykge1xuICAgICAgdGhpcy5ieXRlVG9DaGFyTWFwXyA9IHt9O1xuICAgICAgdGhpcy5jaGFyVG9CeXRlTWFwXyA9IHt9O1xuICAgICAgdGhpcy5ieXRlVG9DaGFyTWFwV2ViU2FmZV8gPSB7fTtcbiAgICAgIHRoaXMuY2hhclRvQnl0ZU1hcFdlYlNhZmVfID0ge307XG5cbiAgICAgIC8vIFdlIHdhbnQgcXVpY2sgbWFwcGluZ3MgYmFjayBhbmQgZm9ydGgsIHNvIHdlIHByZWNvbXB1dGUgdHdvIG1hcHMuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuRU5DT0RFRF9WQUxTLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuYnl0ZVRvQ2hhck1hcF9baV0gPSB0aGlzLkVOQ09ERURfVkFMUy5jaGFyQXQoaSk7XG4gICAgICAgIHRoaXMuY2hhclRvQnl0ZU1hcF9bdGhpcy5ieXRlVG9DaGFyTWFwX1tpXV0gPSBpO1xuICAgICAgICB0aGlzLmJ5dGVUb0NoYXJNYXBXZWJTYWZlX1tpXSA9IHRoaXMuRU5DT0RFRF9WQUxTX1dFQlNBRkUuY2hhckF0KGkpO1xuICAgICAgICB0aGlzLmNoYXJUb0J5dGVNYXBXZWJTYWZlX1t0aGlzLmJ5dGVUb0NoYXJNYXBXZWJTYWZlX1tpXV0gPSBpO1xuXG4gICAgICAgIC8vIEJlIGZvcmdpdmluZyB3aGVuIGRlY29kaW5nIGFuZCBjb3JyZWN0bHkgZGVjb2RlIGJvdGggZW5jb2RpbmdzLlxuICAgICAgICBpZiAoaSA+PSB0aGlzLkVOQ09ERURfVkFMU19CQVNFLmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuY2hhclRvQnl0ZU1hcF9bdGhpcy5FTkNPREVEX1ZBTFNfV0VCU0FGRS5jaGFyQXQoaSldID0gaTtcbiAgICAgICAgICB0aGlzLmNoYXJUb0J5dGVNYXBXZWJTYWZlX1t0aGlzLkVOQ09ERURfVkFMUy5jaGFyQXQoaSldID0gaTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBBbiBlcnJvciBlbmNvdW50ZXJlZCB3aGlsZSBkZWNvZGluZyBiYXNlNjQgc3RyaW5nLlxuICovXG5leHBvcnQgY2xhc3MgRGVjb2RlQmFzZTY0U3RyaW5nRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHJlYWRvbmx5IG5hbWUgPSAnRGVjb2RlQmFzZTY0U3RyaW5nRXJyb3InO1xufVxuXG4vKipcbiAqIFVSTC1zYWZlIGJhc2U2NCBlbmNvZGluZ1xuICovXG5leHBvcnQgY29uc3QgYmFzZTY0RW5jb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgdXRmOEJ5dGVzID0gc3RyaW5nVG9CeXRlQXJyYXkoc3RyKTtcbiAgcmV0dXJuIGJhc2U2NC5lbmNvZGVCeXRlQXJyYXkodXRmOEJ5dGVzLCB0cnVlKTtcbn07XG5cbi8qKlxuICogVVJMLXNhZmUgYmFzZTY0IGVuY29kaW5nICh3aXRob3V0IFwiLlwiIHBhZGRpbmcgaW4gdGhlIGVuZCkuXG4gKiBlLmcuIFVzZWQgaW4gSlNPTiBXZWIgVG9rZW4gKEpXVCkgcGFydHMuXG4gKi9cbmV4cG9ydCBjb25zdCBiYXNlNjR1cmxFbmNvZGVXaXRob3V0UGFkZGluZyA9IGZ1bmN0aW9uIChzdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIFVzZSBiYXNlNjR1cmwgZW5jb2RpbmcgYW5kIHJlbW92ZSBwYWRkaW5nIGluIHRoZSBlbmQgKGRvdCBjaGFyYWN0ZXJzKS5cbiAgcmV0dXJuIGJhc2U2NEVuY29kZShzdHIpLnJlcGxhY2UoL1xcLi9nLCAnJyk7XG59O1xuXG4vKipcbiAqIFVSTC1zYWZlIGJhc2U2NCBkZWNvZGluZ1xuICpcbiAqIE5PVEU6IERPIE5PVCB1c2UgdGhlIGdsb2JhbCBhdG9iKCkgZnVuY3Rpb24gLSBpdCBkb2VzIE5PVCBzdXBwb3J0IHRoZVxuICogYmFzZTY0VXJsIHZhcmlhbnQgZW5jb2RpbmcuXG4gKlxuICogQHBhcmFtIHN0ciBUbyBiZSBkZWNvZGVkXG4gKiBAcmV0dXJuIERlY29kZWQgcmVzdWx0LCBpZiBwb3NzaWJsZVxuICovXG5leHBvcnQgY29uc3QgYmFzZTY0RGVjb2RlID0gZnVuY3Rpb24gKHN0cjogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGJhc2U2NC5kZWNvZGVTdHJpbmcoc3RyLCB0cnVlKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2Jhc2U2NERlY29kZSBmYWlsZWQ6ICcsIGUpO1xuICB9XG4gIHJldHVybiBudWxsO1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIERvIGEgZGVlcC1jb3B5IG9mIGJhc2ljIEphdmFTY3JpcHQgT2JqZWN0cyBvciBBcnJheXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWVwQ29weTxUPih2YWx1ZTogVCk6IFQge1xuICByZXR1cm4gZGVlcEV4dGVuZCh1bmRlZmluZWQsIHZhbHVlKSBhcyBUO1xufVxuXG4vKipcbiAqIENvcHkgcHJvcGVydGllcyBmcm9tIHNvdXJjZSB0byB0YXJnZXQgKHJlY3Vyc2l2ZWx5IGFsbG93cyBleHRlbnNpb25cbiAqIG9mIE9iamVjdHMgYW5kIEFycmF5cykuICBTY2FsYXIgdmFsdWVzIGluIHRoZSB0YXJnZXQgYXJlIG92ZXItd3JpdHRlbi5cbiAqIElmIHRhcmdldCBpcyB1bmRlZmluZWQsIGFuIG9iamVjdCBvZiB0aGUgYXBwcm9wcmlhdGUgdHlwZSB3aWxsIGJlIGNyZWF0ZWRcbiAqIChhbmQgcmV0dXJuZWQpLlxuICpcbiAqIFdlIHJlY3Vyc2l2ZWx5IGNvcHkgYWxsIGNoaWxkIHByb3BlcnRpZXMgb2YgcGxhaW4gT2JqZWN0cyBpbiB0aGUgc291cmNlLSBzb1xuICogdGhhdCBuYW1lc3BhY2UtIGxpa2UgZGljdGlvbmFyaWVzIGFyZSBtZXJnZWQuXG4gKlxuICogTm90ZSB0aGF0IHRoZSB0YXJnZXQgY2FuIGJlIGEgZnVuY3Rpb24sIGluIHdoaWNoIGNhc2UgdGhlIHByb3BlcnRpZXMgaW5cbiAqIHRoZSBzb3VyY2UgT2JqZWN0IGFyZSBjb3BpZWQgb250byBpdCBhcyBzdGF0aWMgcHJvcGVydGllcyBvZiB0aGUgRnVuY3Rpb24uXG4gKlxuICogTm90ZTogd2UgZG9uJ3QgbWVyZ2UgX19wcm90b19fIHRvIHByZXZlbnQgcHJvdG90eXBlIHBvbGx1dGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcEV4dGVuZCh0YXJnZXQ6IHVua25vd24sIHNvdXJjZTogdW5rbm93bik6IHVua25vd24ge1xuICBpZiAoIShzb3VyY2UgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgcmV0dXJuIHNvdXJjZTtcbiAgfVxuXG4gIHN3aXRjaCAoc291cmNlLmNvbnN0cnVjdG9yKSB7XG4gICAgY2FzZSBEYXRlOlxuICAgICAgLy8gVHJlYXQgRGF0ZXMgbGlrZSBzY2FsYXJzOyBpZiB0aGUgdGFyZ2V0IGRhdGUgb2JqZWN0IGhhZCBhbnkgY2hpbGRcbiAgICAgIC8vIHByb3BlcnRpZXMgLSB0aGV5IHdpbGwgYmUgbG9zdCFcbiAgICAgIGNvbnN0IGRhdGVWYWx1ZSA9IHNvdXJjZSBhcyBEYXRlO1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKGRhdGVWYWx1ZS5nZXRUaW1lKCkpO1xuXG4gICAgY2FzZSBPYmplY3Q6XG4gICAgICBpZiAodGFyZ2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGFyZ2V0ID0ge307XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlIEFycmF5OlxuICAgICAgLy8gQWx3YXlzIGNvcHkgdGhlIGFycmF5IHNvdXJjZSBhbmQgb3ZlcndyaXRlIHRoZSB0YXJnZXQuXG4gICAgICB0YXJnZXQgPSBbXTtcbiAgICAgIGJyZWFrO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIE5vdCBhIHBsYWluIE9iamVjdCAtIHRyZWF0IGl0IGFzIGEgc2NhbGFyLlxuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgfVxuXG4gIGZvciAoY29uc3QgcHJvcCBpbiBzb3VyY2UpIHtcbiAgICAvLyB1c2UgaXNWYWxpZEtleSB0byBndWFyZCBhZ2FpbnN0IHByb3RvdHlwZSBwb2xsdXRpb24uIFNlZSBodHRwczovL3NueWsuaW8vdnVsbi9TTllLLUpTLUxPREFTSC00NTAyMDJcbiAgICBpZiAoIXNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwcm9wKSB8fCAhaXNWYWxpZEtleShwcm9wKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgICh0YXJnZXQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW3Byb3BdID0gZGVlcEV4dGVuZChcbiAgICAgICh0YXJnZXQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW3Byb3BdLFxuICAgICAgKHNvdXJjZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbcHJvcF1cbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZEtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4ga2V5ICE9PSAnX19wcm90b19fJztcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIFBvbHlmaWxsIGZvciBgZ2xvYmFsVGhpc2Agb2JqZWN0LlxuICogQHJldHVybnMgdGhlIGBnbG9iYWxUaGlzYCBvYmplY3QgZm9yIHRoZSBnaXZlbiBlbnZpcm9ubWVudC5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdsb2JhbCgpOiB0eXBlb2YgZ2xvYmFsVGhpcyB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfVxuICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9XG4gIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gbG9jYXRlIGdsb2JhbCBvYmplY3QuJyk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgYmFzZTY0RGVjb2RlIH0gZnJvbSAnLi9jcnlwdCc7XG5pbXBvcnQgeyBnZXRHbG9iYWwgfSBmcm9tICcuL2dsb2JhbCc7XG5pbXBvcnQgeyBnZXREZWZhdWx0c0Zyb21Qb3N0aW5zdGFsbCB9IGZyb20gJy4vcG9zdGluc3RhbGwnO1xuXG4vKipcbiAqIEtleXMgZm9yIGV4cGVyaW1lbnRhbCBwcm9wZXJ0aWVzIG9uIHRoZSBgRmlyZWJhc2VEZWZhdWx0c2Agb2JqZWN0LlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgdHlwZSBFeHBlcmltZW50YWxLZXkgPSAnYXV0aFRva2VuU3luY1VSTCcgfCAnYXV0aElkVG9rZW5NYXhBZ2UnO1xuXG4vKipcbiAqIEFuIG9iamVjdCB0aGF0IGNhbiBiZSBpbmplY3RlZCBpbnRvIHRoZSBlbnZpcm9ubWVudCBhcyBfX0ZJUkVCQVNFX0RFRkFVTFRTX18sXG4gKiBlaXRoZXIgYXMgYSBwcm9wZXJ0eSBvZiBnbG9iYWxUaGlzLCBhIHNoZWxsIGVudmlyb25tZW50IHZhcmlhYmxlLCBvciBhXG4gKiBjb29raWUuXG4gKlxuICogVGhpcyBvYmplY3QgY2FuIGJlIHVzZWQgdG8gYXV0b21hdGljYWxseSBjb25maWd1cmUgYW5kIGluaXRpYWxpemVcbiAqIGEgRmlyZWJhc2UgYXBwIGFzIHdlbGwgYXMgYW55IGVtdWxhdG9ycy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRmlyZWJhc2VEZWZhdWx0cyB7XG4gIGNvbmZpZz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGVtdWxhdG9ySG9zdHM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBfYXV0aFRva2VuU3luY1VSTD86IHN0cmluZztcbiAgX2F1dGhJZFRva2VuTWF4QWdlPzogbnVtYmVyO1xuICAvKipcbiAgICogT3ZlcnJpZGUgRmlyZWJhc2UncyBydW50aW1lIGVudmlyb25tZW50IGRldGVjdGlvbiBhbmRcbiAgICogZm9yY2UgdGhlIFNESyB0byBhY3QgYXMgaWYgaXQgd2VyZSBpbiB0aGUgc3BlY2lmaWVkIGVudmlyb25tZW50LlxuICAgKi9cbiAgZm9yY2VFbnZpcm9ubWVudD86ICdicm93c2VyJyB8ICdub2RlJztcbiAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuZGVjbGFyZSBnbG9iYWwge1xuICAvLyBOZWVkIGB2YXJgIGZvciB0aGlzIHRvIHdvcmsuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby12YXJcbiAgdmFyIF9fRklSRUJBU0VfREVGQVVMVFNfXzogRmlyZWJhc2VEZWZhdWx0cyB8IHVuZGVmaW5lZDtcbn1cblxuY29uc3QgZ2V0RGVmYXVsdHNGcm9tR2xvYmFsID0gKCk6IEZpcmViYXNlRGVmYXVsdHMgfCB1bmRlZmluZWQgPT5cbiAgZ2V0R2xvYmFsKCkuX19GSVJFQkFTRV9ERUZBVUxUU19fO1xuXG4vKipcbiAqIEF0dGVtcHQgdG8gcmVhZCBkZWZhdWx0cyBmcm9tIGEgSlNPTiBzdHJpbmcgcHJvdmlkZWQgdG9cbiAqIHByb2Nlc3MoLillbnYoLilfX0ZJUkVCQVNFX0RFRkFVTFRTX18gb3IgYSBKU09OIGZpbGUgd2hvc2UgcGF0aCBpcyBpblxuICogcHJvY2VzcyguKWVudiguKV9fRklSRUJBU0VfREVGQVVMVFNfUEFUSF9fXG4gKiBUaGUgZG90cyBhcmUgaW4gcGFyZW5zIGJlY2F1c2UgY2VydGFpbiBjb21waWxlcnMgKFZpdGU/KSBjYW5ub3RcbiAqIGhhbmRsZSBzZWVpbmcgdGhhdCB2YXJpYWJsZSBpbiBjb21tZW50cy5cbiAqIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZmlyZWJhc2UvZmlyZWJhc2UtanMtc2RrL2lzc3Vlcy82ODM4XG4gKi9cbmNvbnN0IGdldERlZmF1bHRzRnJvbUVudlZhcmlhYmxlID0gKCk6IEZpcmViYXNlRGVmYXVsdHMgfCB1bmRlZmluZWQgPT4ge1xuICBpZiAodHlwZW9mIHByb2Nlc3MgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBwcm9jZXNzLmVudiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgZGVmYXVsdHNKc29uU3RyaW5nID0gcHJvY2Vzcy5lbnYuX19GSVJFQkFTRV9ERUZBVUxUU19fO1xuICBpZiAoZGVmYXVsdHNKc29uU3RyaW5nKSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UoZGVmYXVsdHNKc29uU3RyaW5nKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0RGVmYXVsdHNGcm9tQ29va2llID0gKCk6IEZpcmViYXNlRGVmYXVsdHMgfCB1bmRlZmluZWQgPT4ge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybjtcbiAgfVxuICBsZXQgbWF0Y2g7XG4gIHRyeSB7XG4gICAgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2goL19fRklSRUJBU0VfREVGQVVMVFNfXz0oW147XSspLyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBTb21lIGVudmlyb25tZW50cyBzdWNoIGFzIEFuZ3VsYXIgVW5pdmVyc2FsIFNTUiBoYXZlIGFcbiAgICAvLyBgZG9jdW1lbnRgIG9iamVjdCBidXQgZXJyb3Igb24gYWNjZXNzaW5nIGBkb2N1bWVudC5jb29raWVgLlxuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBkZWNvZGVkID0gbWF0Y2ggJiYgYmFzZTY0RGVjb2RlKG1hdGNoWzFdKTtcbiAgcmV0dXJuIGRlY29kZWQgJiYgSlNPTi5wYXJzZShkZWNvZGVkKTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBfX0ZJUkVCQVNFX0RFRkFVTFRTX18gb2JqZWN0LiBJdCBjaGVja3MgaW4gb3JkZXI6XG4gKiAoMSkgaWYgc3VjaCBhbiBvYmplY3QgZXhpc3RzIGFzIGEgcHJvcGVydHkgb2YgYGdsb2JhbFRoaXNgXG4gKiAoMikgaWYgc3VjaCBhbiBvYmplY3Qgd2FzIHByb3ZpZGVkIG9uIGEgc2hlbGwgZW52aXJvbm1lbnQgdmFyaWFibGVcbiAqICgzKSBpZiBzdWNoIGFuIG9iamVjdCBleGlzdHMgaW4gYSBjb29raWVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGdldERlZmF1bHRzID0gKCk6IEZpcmViYXNlRGVmYXVsdHMgfCB1bmRlZmluZWQgPT4ge1xuICB0cnkge1xuICAgIHJldHVybiAoXG4gICAgICBnZXREZWZhdWx0c0Zyb21Qb3N0aW5zdGFsbCgpIHx8XG4gICAgICBnZXREZWZhdWx0c0Zyb21HbG9iYWwoKSB8fFxuICAgICAgZ2V0RGVmYXVsdHNGcm9tRW52VmFyaWFibGUoKSB8fFxuICAgICAgZ2V0RGVmYXVsdHNGcm9tQ29va2llKClcbiAgICApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLyoqXG4gICAgICogQ2F0Y2gtYWxsIGZvciBiZWluZyB1bmFibGUgdG8gZ2V0IF9fRklSRUJBU0VfREVGQVVMVFNfXyBkdWVcbiAgICAgKiB0byBhbnkgZW52aXJvbm1lbnQgY2FzZSB3ZSBoYXZlIG5vdCBhY2NvdW50ZWQgZm9yLiBMb2cgdG9cbiAgICAgKiBpbmZvIGluc3RlYWQgb2Ygc3dhbGxvd2luZyBzbyB3ZSBjYW4gZmluZCB0aGVzZSB1bmtub3duIGNhc2VzXG4gICAgICogYW5kIGFkZCBwYXRocyBmb3IgdGhlbSBpZiBuZWVkZWQuXG4gICAgICovXG4gICAgY29uc29sZS5pbmZvKGBVbmFibGUgdG8gZ2V0IF9fRklSRUJBU0VfREVGQVVMVFNfXyBkdWUgdG86ICR7ZX1gKTtcbiAgICByZXR1cm47XG4gIH1cbn07XG5cbi8qKlxuICogUmV0dXJucyBlbXVsYXRvciBob3N0IHN0b3JlZCBpbiB0aGUgX19GSVJFQkFTRV9ERUZBVUxUU19fIG9iamVjdFxuICogZm9yIHRoZSBnaXZlbiBwcm9kdWN0LlxuICogQHJldHVybnMgYSBVUkwgaG9zdCBmb3JtYXR0ZWQgbGlrZSBgMTI3LjAuMC4xOjk5OTlgIG9yIGBbOjoxXTo0MDAwYCBpZiBhdmFpbGFibGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGdldERlZmF1bHRFbXVsYXRvckhvc3QgPSAoXG4gIHByb2R1Y3ROYW1lOiBzdHJpbmdcbik6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiBnZXREZWZhdWx0cygpPy5lbXVsYXRvckhvc3RzPy5bcHJvZHVjdE5hbWVdO1xuXG4vKipcbiAqIFJldHVybnMgZW11bGF0b3IgaG9zdG5hbWUgYW5kIHBvcnQgc3RvcmVkIGluIHRoZSBfX0ZJUkVCQVNFX0RFRkFVTFRTX18gb2JqZWN0XG4gKiBmb3IgdGhlIGdpdmVuIHByb2R1Y3QuXG4gKiBAcmV0dXJucyBhIHBhaXIgb2YgaG9zdG5hbWUgYW5kIHBvcnQgbGlrZSBgW1wiOjoxXCIsIDQwMDBdYCBpZiBhdmFpbGFibGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGdldERlZmF1bHRFbXVsYXRvckhvc3RuYW1lQW5kUG9ydCA9IChcbiAgcHJvZHVjdE5hbWU6IHN0cmluZ1xuKTogW2hvc3RuYW1lOiBzdHJpbmcsIHBvcnQ6IG51bWJlcl0gfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCBob3N0ID0gZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdChwcm9kdWN0TmFtZSk7XG4gIGlmICghaG9zdCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgY29uc3Qgc2VwYXJhdG9ySW5kZXggPSBob3N0Lmxhc3RJbmRleE9mKCc6Jyk7IC8vIEZpbmRpbmcgdGhlIGxhc3Qgc2luY2UgSVB2NiBhZGRyIGFsc28gaGFzIGNvbG9ucy5cbiAgaWYgKHNlcGFyYXRvckluZGV4IDw9IDAgfHwgc2VwYXJhdG9ySW5kZXggKyAxID09PSBob3N0Lmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBob3N0ICR7aG9zdH0gd2l0aCBubyBzZXBhcmF0ZSBob3N0bmFtZSBhbmQgcG9ydCFgKTtcbiAgfVxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1nbG9iYWxzXG4gIGNvbnN0IHBvcnQgPSBwYXJzZUludChob3N0LnN1YnN0cmluZyhzZXBhcmF0b3JJbmRleCArIDEpLCAxMCk7XG4gIGlmIChob3N0WzBdID09PSAnWycpIHtcbiAgICAvLyBCcmFja2V0LXF1b3RlZCBgW2lwdjZhZGRyXTpwb3J0YCA9PiByZXR1cm4gXCJpcHY2YWRkclwiICh3aXRob3V0IGJyYWNrZXRzKS5cbiAgICByZXR1cm4gW2hvc3Quc3Vic3RyaW5nKDEsIHNlcGFyYXRvckluZGV4IC0gMSksIHBvcnRdO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbaG9zdC5zdWJzdHJpbmcoMCwgc2VwYXJhdG9ySW5kZXgpLCBwb3J0XTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXR1cm5zIEZpcmViYXNlIGFwcCBjb25maWcgc3RvcmVkIGluIHRoZSBfX0ZJUkVCQVNFX0RFRkFVTFRTX18gb2JqZWN0LlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZ2V0RGVmYXVsdEFwcENvbmZpZyA9ICgpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHwgdW5kZWZpbmVkID0+XG4gIGdldERlZmF1bHRzKCk/LmNvbmZpZztcblxuLyoqXG4gKiBSZXR1cm5zIGFuIGV4cGVyaW1lbnRhbCBzZXR0aW5nIG9uIHRoZSBfX0ZJUkVCQVNFX0RFRkFVTFRTX18gb2JqZWN0IChwcm9wZXJ0aWVzXG4gKiBwcmVmaXhlZCBieSBcIl9cIilcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGdldEV4cGVyaW1lbnRhbFNldHRpbmcgPSA8VCBleHRlbmRzIEV4cGVyaW1lbnRhbEtleT4oXG4gIG5hbWU6IFRcbik6IEZpcmViYXNlRGVmYXVsdHNbYF8ke1R9YF0gPT5cbiAgZ2V0RGVmYXVsdHMoKT8uW2BfJHtuYW1lfWBdIGFzIEZpcmViYXNlRGVmYXVsdHNbYF8ke1R9YF07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IGNsYXNzIERlZmVycmVkPFI+IHtcbiAgcHJvbWlzZTogUHJvbWlzZTxSPjtcbiAgcmVqZWN0OiAodmFsdWU/OiB1bmtub3duKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIHJlc29sdmU6ICh2YWx1ZT86IHVua25vd24pID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5wcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5yZXNvbHZlID0gcmVzb2x2ZSBhcyAodmFsdWU/OiB1bmtub3duKSA9PiB2b2lkO1xuICAgICAgdGhpcy5yZWplY3QgPSByZWplY3QgYXMgKHZhbHVlPzogdW5rbm93bikgPT4gdm9pZDtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdXIgQVBJIGludGVybmFscyBhcmUgbm90IHByb21pc2lmaWVkIGFuZCBjYW5ub3QgYmVjYXVzZSBvdXIgY2FsbGJhY2sgQVBJcyBoYXZlIHN1YnRsZSBleHBlY3RhdGlvbnMgYXJvdW5kXG4gICAqIGludm9raW5nIHByb21pc2VzIGlubGluZSwgd2hpY2ggUHJvbWlzZXMgYXJlIGZvcmJpZGRlbiB0byBkby4gVGhpcyBtZXRob2QgYWNjZXB0cyBhbiBvcHRpb25hbCBub2RlLXN0eWxlIGNhbGxiYWNrXG4gICAqIGFuZCByZXR1cm5zIGEgbm9kZS1zdHlsZSBjYWxsYmFjayB3aGljaCB3aWxsIHJlc29sdmUgb3IgcmVqZWN0IHRoZSBEZWZlcnJlZCdzIHByb21pc2UuXG4gICAqL1xuICB3cmFwQ2FsbGJhY2soXG4gICAgY2FsbGJhY2s/OiAoZXJyb3I/OiB1bmtub3duLCB2YWx1ZT86IHVua25vd24pID0+IHZvaWRcbiAgKTogKGVycm9yOiB1bmtub3duLCB2YWx1ZT86IHVua25vd24pID0+IHZvaWQge1xuICAgIHJldHVybiAoZXJyb3IsIHZhbHVlPykgPT4ge1xuICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgIHRoaXMucmVqZWN0KGVycm9yKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmVzb2x2ZSh2YWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIEF0dGFjaGluZyBub29wIGhhbmRsZXIganVzdCBpbiBjYXNlIGRldmVsb3BlciB3YXNuJ3QgZXhwZWN0aW5nXG4gICAgICAgIC8vIHByb21pc2VzXG4gICAgICAgIHRoaXMucHJvbWlzZS5jYXRjaCgoKSA9PiB7fSk7XG5cbiAgICAgICAgLy8gU29tZSBvZiBvdXIgY2FsbGJhY2tzIGRvbid0IGV4cGVjdCBhIHZhbHVlIGFuZCBvdXIgb3duIHRlc3RzXG4gICAgICAgIC8vIGFzc2VydCB0aGF0IHRoZSBwYXJhbWV0ZXIgbGVuZ3RoIGlzIDFcbiAgICAgICAgaWYgKGNhbGxiYWNrLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIGNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYWxsYmFjayhlcnJvciwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI1IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgaG9zdCBpcyBhIGNsb3VkIHdvcmtzdGF0aW9uIG9yIG5vdC5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ2xvdWRXb3Jrc3RhdGlvbih1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAvLyBgaXNDbG91ZFdvcmtzdGF0aW9uYCBpcyBjYWxsZWQgd2l0aG91dCBwcm90b2NvbCBpbiBjZXJ0YWluIGNvbm5lY3QqRW11bGF0b3IgZnVuY3Rpb25zXG4gIC8vIEluIEhUVFAgcmVxdWVzdCBidWlsZGVycywgaXQncyBjYWxsZWQgd2l0aCB0aGUgcHJvdG9jb2wuXG4gIC8vIElmIGNhbGxlZCB3aXRoIHByb3RvY29sIHByZWZpeCwgaXQncyBhIHZhbGlkIFVSTCwgc28gd2UgZXh0cmFjdCB0aGUgaG9zdG5hbWVcbiAgLy8gSWYgY2FsbGVkIHdpdGhvdXQsIHdlIGFzc3VtZSB0aGUgc3RyaW5nIGlzIHRoZSBob3N0bmFtZS5cbiAgdHJ5IHtcbiAgICBjb25zdCBob3N0ID1cbiAgICAgIHVybC5zdGFydHNXaXRoKCdodHRwOi8vJykgfHwgdXJsLnN0YXJ0c1dpdGgoJ2h0dHBzOi8vJylcbiAgICAgICAgPyBuZXcgVVJMKHVybCkuaG9zdG5hbWVcbiAgICAgICAgOiB1cmw7XG4gICAgcmV0dXJuIGhvc3QuZW5kc1dpdGgoJy5jbG91ZHdvcmtzdGF0aW9ucy5kZXYnKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogTWFrZXMgYSBmZXRjaCByZXF1ZXN0IHRvIHRoZSBnaXZlbiBzZXJ2ZXIuXG4gKiBNb3N0bHkgdXNlZCBmb3IgZm9yd2FyZGluZyBjb29raWVzIGluIEZpcmViYXNlIFN0dWRpby5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBpbmdTZXJ2ZXIoZW5kcG9pbnQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBmZXRjaChlbmRwb2ludCwge1xuICAgIGNyZWRlbnRpYWxzOiAnaW5jbHVkZSdcbiAgfSk7XG4gIHJldHVybiByZXN1bHQub2s7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgYmFzZTY0dXJsRW5jb2RlV2l0aG91dFBhZGRpbmcgfSBmcm9tICcuL2NyeXB0JztcbmltcG9ydCB7IGlzQ2xvdWRXb3Jrc3RhdGlvbiB9IGZyb20gJy4vdXJsJztcblxuLy8gRmlyZWJhc2UgQXV0aCB0b2tlbnMgY29udGFpbiBzbmFrZV9jYXNlIGNsYWltcyBmb2xsb3dpbmcgdGhlIEpXVCBzdGFuZGFyZCAvIGNvbnZlbnRpb24uXG4vKiBlc2xpbnQtZGlzYWJsZSBjYW1lbGNhc2UgKi9cblxuZXhwb3J0IHR5cGUgRmlyZWJhc2VTaWduSW5Qcm92aWRlciA9XG4gIHwgJ2N1c3RvbSdcbiAgfCAnZW1haWwnXG4gIHwgJ3Bhc3N3b3JkJ1xuICB8ICdwaG9uZSdcbiAgfCAnYW5vbnltb3VzJ1xuICB8ICdnb29nbGUuY29tJ1xuICB8ICdmYWNlYm9vay5jb20nXG4gIHwgJ2dpdGh1Yi5jb20nXG4gIHwgJ3R3aXR0ZXIuY29tJ1xuICB8ICdtaWNyb3NvZnQuY29tJ1xuICB8ICdhcHBsZS5jb20nO1xuXG5pbnRlcmZhY2UgRmlyZWJhc2VJZFRva2VuIHtcbiAgLy8gQWx3YXlzIHNldCB0byBodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vUFJPSkVDVF9JRFxuICBpc3M6IHN0cmluZztcblxuICAvLyBBbHdheXMgc2V0IHRvIFBST0pFQ1RfSURcbiAgYXVkOiBzdHJpbmc7XG5cbiAgLy8gVGhlIHVzZXIncyB1bmlxdWUgSURcbiAgc3ViOiBzdHJpbmc7XG5cbiAgLy8gVGhlIHRva2VuIGlzc3VlIHRpbWUsIGluIHNlY29uZHMgc2luY2UgZXBvY2hcbiAgaWF0OiBudW1iZXI7XG5cbiAgLy8gVGhlIHRva2VuIGV4cGlyeSB0aW1lLCBub3JtYWxseSAnaWF0JyArIDM2MDBcbiAgZXhwOiBudW1iZXI7XG5cbiAgLy8gVGhlIHVzZXIncyB1bmlxdWUgSUQuIE11c3QgYmUgZXF1YWwgdG8gJ3N1YidcbiAgdXNlcl9pZDogc3RyaW5nO1xuXG4gIC8vIFRoZSB0aW1lIHRoZSB1c2VyIGF1dGhlbnRpY2F0ZWQsIG5vcm1hbGx5ICdpYXQnXG4gIGF1dGhfdGltZTogbnVtYmVyO1xuXG4gIC8vIFRoZSBzaWduIGluIHByb3ZpZGVyLCBvbmx5IHNldCB3aGVuIHRoZSBwcm92aWRlciBpcyAnYW5vbnltb3VzJ1xuICBwcm92aWRlcl9pZD86ICdhbm9ueW1vdXMnO1xuXG4gIC8vIFRoZSB1c2VyJ3MgcHJpbWFyeSBlbWFpbFxuICBlbWFpbD86IHN0cmluZztcblxuICAvLyBUaGUgdXNlcidzIGVtYWlsIHZlcmlmaWNhdGlvbiBzdGF0dXNcbiAgZW1haWxfdmVyaWZpZWQ/OiBib29sZWFuO1xuXG4gIC8vIFRoZSB1c2VyJ3MgcHJpbWFyeSBwaG9uZSBudW1iZXJcbiAgcGhvbmVfbnVtYmVyPzogc3RyaW5nO1xuXG4gIC8vIFRoZSB1c2VyJ3MgZGlzcGxheSBuYW1lXG4gIG5hbWU/OiBzdHJpbmc7XG5cbiAgLy8gVGhlIHVzZXIncyBwcm9maWxlIHBob3RvIFVSTFxuICBwaWN0dXJlPzogc3RyaW5nO1xuXG4gIC8vIEluZm9ybWF0aW9uIG9uIGFsbCBpZGVudGl0aWVzIGxpbmtlZCB0byB0aGlzIHVzZXJcbiAgZmlyZWJhc2U6IHtcbiAgICAvLyBUaGUgcHJpbWFyeSBzaWduLWluIHByb3ZpZGVyXG4gICAgc2lnbl9pbl9wcm92aWRlcjogRmlyZWJhc2VTaWduSW5Qcm92aWRlcjtcblxuICAgIC8vIEEgbWFwIG9mIHByb3ZpZGVycyB0byB0aGUgdXNlcidzIGxpc3Qgb2YgdW5pcXVlIGlkZW50aWZpZXJzIGZyb21cbiAgICAvLyBlYWNoIHByb3ZpZGVyXG4gICAgaWRlbnRpdGllcz86IHsgW3Byb3ZpZGVyIGluIEZpcmViYXNlU2lnbkluUHJvdmlkZXJdPzogc3RyaW5nW10gfTtcbiAgfTtcblxuICAvLyBDdXN0b20gY2xhaW1zIHNldCBieSB0aGUgZGV2ZWxvcGVyXG4gIFtjbGFpbTogc3RyaW5nXTogdW5rbm93bjtcblxuICB1aWQ/OiBuZXZlcjsgLy8gVHJ5IHRvIGNhdGNoIGEgY29tbW9uIG1pc3Rha2Ugb2YgXCJ1aWRcIiAoc2hvdWxkIGJlIFwic3ViXCIgaW5zdGVhZCkuXG59XG5cbmV4cG9ydCB0eXBlIEVtdWxhdG9yTW9ja1Rva2VuT3B0aW9ucyA9ICh7IHVzZXJfaWQ6IHN0cmluZyB9IHwgeyBzdWI6IHN0cmluZyB9KSAmXG4gIFBhcnRpYWw8RmlyZWJhc2VJZFRva2VuPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1vY2tVc2VyVG9rZW4oXG4gIHRva2VuOiBFbXVsYXRvck1vY2tUb2tlbk9wdGlvbnMsXG4gIHByb2plY3RJZD86IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgaWYgKHRva2VuLnVpZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdUaGUgXCJ1aWRcIiBmaWVsZCBpcyBubyBsb25nZXIgc3VwcG9ydGVkIGJ5IG1vY2tVc2VyVG9rZW4uIFBsZWFzZSB1c2UgXCJzdWJcIiBpbnN0ZWFkIGZvciBGaXJlYmFzZSBBdXRoIFVzZXIgSUQuJ1xuICAgICk7XG4gIH1cbiAgLy8gVW5zZWN1cmVkIEpXVHMgdXNlIFwibm9uZVwiIGFzIHRoZSBhbGdvcml0aG0uXG4gIGNvbnN0IGhlYWRlciA9IHtcbiAgICBhbGc6ICdub25lJyxcbiAgICB0eXBlOiAnSldUJ1xuICB9O1xuXG4gIGNvbnN0IHByb2plY3QgPSBwcm9qZWN0SWQgfHwgJ2RlbW8tcHJvamVjdCc7XG4gIGNvbnN0IGlhdCA9IHRva2VuLmlhdCB8fCAwO1xuICBjb25zdCBzdWIgPSB0b2tlbi5zdWIgfHwgdG9rZW4udXNlcl9pZDtcbiAgaWYgKCFzdWIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtb2NrVXNlclRva2VuIG11c3QgY29udGFpbiAnc3ViJyBvciAndXNlcl9pZCcgZmllbGQhXCIpO1xuICB9XG5cbiAgY29uc3QgcGF5bG9hZDogRmlyZWJhc2VJZFRva2VuID0ge1xuICAgIC8vIFNldCBhbGwgcmVxdWlyZWQgZmllbGRzIHRvIGRlY2VudCBkZWZhdWx0c1xuICAgIGlzczogYGh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS8ke3Byb2plY3R9YCxcbiAgICBhdWQ6IHByb2plY3QsXG4gICAgaWF0LFxuICAgIGV4cDogaWF0ICsgMzYwMCxcbiAgICBhdXRoX3RpbWU6IGlhdCxcbiAgICBzdWIsXG4gICAgdXNlcl9pZDogc3ViLFxuICAgIGZpcmViYXNlOiB7XG4gICAgICBzaWduX2luX3Byb3ZpZGVyOiAnY3VzdG9tJyxcbiAgICAgIGlkZW50aXRpZXM6IHt9XG4gICAgfSxcblxuICAgIC8vIE92ZXJyaWRlIHdpdGggdXNlciBvcHRpb25zXG4gICAgLi4udG9rZW5cbiAgfTtcblxuICAvLyBVbnNlY3VyZWQgSldUcyB1c2UgdGhlIGVtcHR5IHN0cmluZyBhcyBhIHNpZ25hdHVyZS5cbiAgY29uc3Qgc2lnbmF0dXJlID0gJyc7XG4gIHJldHVybiBbXG4gICAgYmFzZTY0dXJsRW5jb2RlV2l0aG91dFBhZGRpbmcoSlNPTi5zdHJpbmdpZnkoaGVhZGVyKSksXG4gICAgYmFzZTY0dXJsRW5jb2RlV2l0aG91dFBhZGRpbmcoSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpLFxuICAgIHNpZ25hdHVyZVxuICBdLmpvaW4oJy4nKTtcbn1cblxuaW50ZXJmYWNlIEVtdWxhdG9yU3RhdHVzTWFwIHtcbiAgW25hbWU6IHN0cmluZ106IGJvb2xlYW47XG59XG5jb25zdCBlbXVsYXRvclN0YXR1czogRW11bGF0b3JTdGF0dXNNYXAgPSB7fTtcblxuaW50ZXJmYWNlIEVtdWxhdG9yU3VtbWFyeSB7XG4gIHByb2Q6IHN0cmluZ1tdO1xuICBlbXVsYXRvcjogc3RyaW5nW107XG59XG5cbi8vIENoZWNrcyB3aGV0aGVyIGFueSBwcm9kdWN0cyBhcmUgcnVubmluZyBvbiBhbiBlbXVsYXRvclxuZnVuY3Rpb24gZ2V0RW11bGF0b3JTdW1tYXJ5KCk6IEVtdWxhdG9yU3VtbWFyeSB7XG4gIGNvbnN0IHN1bW1hcnk6IEVtdWxhdG9yU3VtbWFyeSA9IHtcbiAgICBwcm9kOiBbXSxcbiAgICBlbXVsYXRvcjogW11cbiAgfTtcbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZW11bGF0b3JTdGF0dXMpKSB7XG4gICAgaWYgKGVtdWxhdG9yU3RhdHVzW2tleV0pIHtcbiAgICAgIHN1bW1hcnkuZW11bGF0b3IucHVzaChrZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdW1tYXJ5LnByb2QucHVzaChrZXkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3VtbWFyeTtcbn1cblxuZnVuY3Rpb24gZ2V0T3JDcmVhdGVFbChpZDogc3RyaW5nKTogeyBjcmVhdGVkOiBib29sZWFuOyBlbGVtZW50OiBIVE1MRWxlbWVudCB9IHtcbiAgbGV0IHBhcmVudERpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKTtcbiAgbGV0IGNyZWF0ZWQgPSBmYWxzZTtcbiAgaWYgKCFwYXJlbnREaXYpIHtcbiAgICBwYXJlbnREaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBwYXJlbnREaXYuc2V0QXR0cmlidXRlKCdpZCcsIGlkKTtcbiAgICBjcmVhdGVkID0gdHJ1ZTtcbiAgfVxuICByZXR1cm4geyBjcmVhdGVkLCBlbGVtZW50OiBwYXJlbnREaXYgfTtcbn1cblxubGV0IHByZXZpb3VzbHlEaXNtaXNzZWQgPSBmYWxzZTtcbi8qKlxuICogVXBkYXRlcyBFbXVsYXRvciBCYW5uZXIuIFByaW1hcmlseSB1c2VkIGZvciBGaXJlYmFzZSBTdHVkaW9cbiAqIEBwYXJhbSBuYW1lXG4gKiBAcGFyYW0gaXNSdW5uaW5nRW11bGF0b3JcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUVtdWxhdG9yQmFubmVyKFxuICBuYW1lOiBzdHJpbmcsXG4gIGlzUnVubmluZ0VtdWxhdG9yOiBib29sZWFuXG4pOiB2b2lkIHtcbiAgaWYgKFxuICAgIHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnIHx8XG4gICAgdHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJyB8fFxuICAgICFpc0Nsb3VkV29ya3N0YXRpb24od2luZG93LmxvY2F0aW9uLmhvc3QpIHx8XG4gICAgZW11bGF0b3JTdGF0dXNbbmFtZV0gPT09IGlzUnVubmluZ0VtdWxhdG9yIHx8XG4gICAgZW11bGF0b3JTdGF0dXNbbmFtZV0gfHwgLy8gSWYgYWxyZWFkeSBzZXQgdG8gdXNlIGVtdWxhdG9yLCBjYW4ndCBnbyBiYWNrIHRvIHByb2QuXG4gICAgcHJldmlvdXNseURpc21pc3NlZFxuICApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBlbXVsYXRvclN0YXR1c1tuYW1lXSA9IGlzUnVubmluZ0VtdWxhdG9yO1xuXG4gIGZ1bmN0aW9uIHByZWZpeGVkSWQoaWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGBfX2ZpcmViYXNlX19iYW5uZXJfXyR7aWR9YDtcbiAgfVxuICBjb25zdCBiYW5uZXJJZCA9ICdfX2ZpcmViYXNlX19iYW5uZXInO1xuICBjb25zdCBzdW1tYXJ5ID0gZ2V0RW11bGF0b3JTdW1tYXJ5KCk7XG4gIGNvbnN0IHNob3dFcnJvciA9IHN1bW1hcnkucHJvZC5sZW5ndGggPiAwO1xuXG4gIGZ1bmN0aW9uIHRlYXJEb3duKCk6IHZvaWQge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChiYW5uZXJJZCk7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgIGVsZW1lbnQucmVtb3ZlKCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2V0dXBCYW5uZXJTdHlsZXMoYmFubmVyRWw6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgYmFubmVyRWwuc3R5bGUuZGlzcGxheSA9ICdmbGV4JztcbiAgICBiYW5uZXJFbC5zdHlsZS5iYWNrZ3JvdW5kID0gJyM3ZmFhZjAnO1xuICAgIGJhbm5lckVsLnN0eWxlLnBvc2l0aW9uID0gJ2ZpeGVkJztcbiAgICBiYW5uZXJFbC5zdHlsZS5ib3R0b20gPSAnNXB4JztcbiAgICBiYW5uZXJFbC5zdHlsZS5sZWZ0ID0gJzVweCc7XG4gICAgYmFubmVyRWwuc3R5bGUucGFkZGluZyA9ICcuNWVtJztcbiAgICBiYW5uZXJFbC5zdHlsZS5ib3JkZXJSYWRpdXMgPSAnNXB4JztcbiAgICBiYW5uZXJFbC5zdHlsZS5hbGlnbkl0ZW1zID0gJ2NlbnRlcic7XG4gIH1cblxuICBmdW5jdGlvbiBzZXR1cEljb25TdHlsZXMocHJlcGVuZEljb246IFNWR0VsZW1lbnQsIGljb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgcHJlcGVuZEljb24uc2V0QXR0cmlidXRlKCd3aWR0aCcsICcyNCcpO1xuICAgIHByZXBlbmRJY29uLnNldEF0dHJpYnV0ZSgnaWQnLCBpY29uSWQpO1xuICAgIHByZXBlbmRJY29uLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgJzI0Jyk7XG4gICAgcHJlcGVuZEljb24uc2V0QXR0cmlidXRlKCd2aWV3Qm94JywgJzAgMCAyNCAyNCcpO1xuICAgIHByZXBlbmRJY29uLnNldEF0dHJpYnV0ZSgnZmlsbCcsICdub25lJyk7XG4gICAgcHJlcGVuZEljb24uc3R5bGUubWFyZ2luTGVmdCA9ICctNnB4JztcbiAgfVxuXG4gIGZ1bmN0aW9uIHNldHVwQ2xvc2VCdG4oKTogSFRNTFNwYW5FbGVtZW50IHtcbiAgICBjb25zdCBjbG9zZUJ0biA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICBjbG9zZUJ0bi5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcic7XG4gICAgY2xvc2VCdG4uc3R5bGUubWFyZ2luTGVmdCA9ICcxNnB4JztcbiAgICBjbG9zZUJ0bi5zdHlsZS5mb250U2l6ZSA9ICcyNHB4JztcbiAgICBjbG9zZUJ0bi5pbm5lckhUTUwgPSAnICZ0aW1lczsnO1xuICAgIGNsb3NlQnRuLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgICBwcmV2aW91c2x5RGlzbWlzc2VkID0gdHJ1ZTtcbiAgICAgIHRlYXJEb3duKCk7XG4gICAgfTtcbiAgICByZXR1cm4gY2xvc2VCdG47XG4gIH1cblxuICBmdW5jdGlvbiBzZXR1cExpbmtTdHlsZXMoXG4gICAgbGVhcm5Nb3JlTGluazogSFRNTEFuY2hvckVsZW1lbnQsXG4gICAgbGVhcm5Nb3JlSWQ6IHN0cmluZ1xuICApOiB2b2lkIHtcbiAgICBsZWFybk1vcmVMaW5rLnNldEF0dHJpYnV0ZSgnaWQnLCBsZWFybk1vcmVJZCk7XG4gICAgbGVhcm5Nb3JlTGluay5pbm5lclRleHQgPSAnTGVhcm4gbW9yZSc7XG4gICAgbGVhcm5Nb3JlTGluay5ocmVmID1cbiAgICAgICdodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy9zdHVkaW8vcHJldmlldy1hcHBzI3ByZXZpZXctYmFja2VuZCc7XG4gICAgbGVhcm5Nb3JlTGluay5zZXRBdHRyaWJ1dGUoJ3RhcmdldCcsICdfX2JsYW5rJyk7XG4gICAgbGVhcm5Nb3JlTGluay5zdHlsZS5wYWRkaW5nTGVmdCA9ICc1cHgnO1xuICAgIGxlYXJuTW9yZUxpbmsuc3R5bGUudGV4dERlY29yYXRpb24gPSAndW5kZXJsaW5lJztcbiAgfVxuXG4gIGZ1bmN0aW9uIHNldHVwRG9tKCk6IHZvaWQge1xuICAgIGNvbnN0IGJhbm5lciA9IGdldE9yQ3JlYXRlRWwoYmFubmVySWQpO1xuICAgIGNvbnN0IGZpcmViYXNlVGV4dElkID0gcHJlZml4ZWRJZCgndGV4dCcpO1xuICAgIGNvbnN0IGZpcmViYXNlVGV4dDogSFRNTFNwYW5FbGVtZW50ID1cbiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGZpcmViYXNlVGV4dElkKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgY29uc3QgbGVhcm5Nb3JlSWQgPSBwcmVmaXhlZElkKCdsZWFybm1vcmUnKTtcbiAgICBjb25zdCBsZWFybk1vcmVMaW5rOiBIVE1MQW5jaG9yRWxlbWVudCA9XG4gICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobGVhcm5Nb3JlSWQpIGFzIEhUTUxBbmNob3JFbGVtZW50KSB8fFxuICAgICAgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgIGNvbnN0IHByZXBlbmRJY29uSWQgPSBwcmVmaXhlZElkKCdwcmVwcmVuZEljb24nKTtcbiAgICBjb25zdCBwcmVwZW5kSWNvbjogU1ZHRWxlbWVudCA9XG4gICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXG4gICAgICAgIHByZXBlbmRJY29uSWRcbiAgICAgICkgYXMgSFRNTE9yU1ZHRWxlbWVudCBhcyBTVkdFbGVtZW50KSB8fFxuICAgICAgZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsICdzdmcnKTtcbiAgICBpZiAoYmFubmVyLmNyZWF0ZWQpIHtcbiAgICAgIC8vIHVwZGF0ZSBzdHlsZXNcbiAgICAgIGNvbnN0IGJhbm5lckVsID0gYmFubmVyLmVsZW1lbnQ7XG4gICAgICBzZXR1cEJhbm5lclN0eWxlcyhiYW5uZXJFbCk7XG4gICAgICBzZXR1cExpbmtTdHlsZXMobGVhcm5Nb3JlTGluaywgbGVhcm5Nb3JlSWQpO1xuICAgICAgY29uc3QgY2xvc2VCdG4gPSBzZXR1cENsb3NlQnRuKCk7XG4gICAgICBzZXR1cEljb25TdHlsZXMocHJlcGVuZEljb24sIHByZXBlbmRJY29uSWQpO1xuICAgICAgYmFubmVyRWwuYXBwZW5kKHByZXBlbmRJY29uLCBmaXJlYmFzZVRleHQsIGxlYXJuTW9yZUxpbmssIGNsb3NlQnRuKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYmFubmVyRWwpO1xuICAgIH1cblxuICAgIGlmIChzaG93RXJyb3IpIHtcbiAgICAgIGZpcmViYXNlVGV4dC5pbm5lclRleHQgPSBgUHJldmlldyBiYWNrZW5kIGRpc2Nvbm5lY3RlZC5gO1xuICAgICAgcHJlcGVuZEljb24uaW5uZXJIVE1MID0gYDxnIGNsaXAtcGF0aD1cInVybCgjY2xpcDBfNjAxM18zMzg1OClcIj5cbjxwYXRoIGQ9XCJNNC44IDE3LjZMMTIgNS42TDE5LjIgMTcuNkg0LjhaTTYuOTE2NjcgMTYuNEgxNy4wODMzTDEyIDcuOTMzMzNMNi45MTY2NyAxNi40Wk0xMiAxNS42QzEyLjE2NjcgMTUuNiAxMi4zMDU2IDE1LjU0NDQgMTIuNDE2NyAxNS40MzMzQzEyLjUzODkgMTUuMzExMSAxMi42IDE1LjE2NjcgMTIuNiAxNUMxMi42IDE0LjgzMzMgMTIuNTM4OSAxNC42OTQ0IDEyLjQxNjcgMTQuNTgzM0MxMi4zMDU2IDE0LjQ2MTEgMTIuMTY2NyAxNC40IDEyIDE0LjRDMTEuODMzMyAxNC40IDExLjY4ODkgMTQuNDYxMSAxMS41NjY3IDE0LjU4MzNDMTEuNDU1NiAxNC42OTQ0IDExLjQgMTQuODMzMyAxMS40IDE1QzExLjQgMTUuMTY2NyAxMS40NTU2IDE1LjMxMTEgMTEuNTY2NyAxNS40MzMzQzExLjY4ODkgMTUuNTQ0NCAxMS44MzMzIDE1LjYgMTIgMTUuNlpNMTEuNCAxMy42SDEyLjZWMTAuNEgxMS40VjEzLjZaXCIgZmlsbD1cIiMyMTIxMjFcIi8+XG48L2c+XG48ZGVmcz5cbjxjbGlwUGF0aCBpZD1cImNsaXAwXzYwMTNfMzM4NThcIj5cbjxyZWN0IHdpZHRoPVwiMjRcIiBoZWlnaHQ9XCIyNFwiIGZpbGw9XCJ3aGl0ZVwiLz5cbjwvY2xpcFBhdGg+XG48L2RlZnM+YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJlcGVuZEljb24uaW5uZXJIVE1MID0gYDxnIGNsaXAtcGF0aD1cInVybCgjY2xpcDBfNjA4M18zNDgwNClcIj5cbjxwYXRoIGQ9XCJNMTEuNCAxNS4ySDEyLjZWMTEuMkgxMS40VjE1LjJaTTEyIDEwQzEyLjE2NjcgMTAgMTIuMzA1NiA5Ljk0NDQ0IDEyLjQxNjcgOS44MzMzM0MxMi41Mzg5IDkuNzExMTEgMTIuNiA5LjU2NjY3IDEyLjYgOS40QzEyLjYgOS4yMzMzMyAxMi41Mzg5IDkuMDk0NDQgMTIuNDE2NyA4Ljk4MzMzQzEyLjMwNTYgOC44NjExMSAxMi4xNjY3IDguOCAxMiA4LjhDMTEuODMzMyA4LjggMTEuNjg4OSA4Ljg2MTExIDExLjU2NjcgOC45ODMzM0MxMS40NTU2IDkuMDk0NDQgMTEuNCA5LjIzMzMzIDExLjQgOS40QzExLjQgOS41NjY2NyAxMS40NTU2IDkuNzExMTEgMTEuNTY2NyA5LjgzMzMzQzExLjY4ODkgOS45NDQ0NCAxMS44MzMzIDEwIDEyIDEwWk0xMiAxOC40QzExLjEyMjIgMTguNCAxMC4yOTQ0IDE4LjIzMzMgOS41MTY2NyAxNy45QzguNzM4ODkgMTcuNTY2NyA4LjA1NTU2IDE3LjExMTEgNy40NjY2NyAxNi41MzMzQzYuODg4ODkgMTUuOTQ0NCA2LjQzMzMzIDE1LjI2MTEgNi4xIDE0LjQ4MzNDNS43NjY2NyAxMy43MDU2IDUuNiAxMi44Nzc4IDUuNiAxMkM1LjYgMTEuMTExMSA1Ljc2NjY3IDEwLjI4MzMgNi4xIDkuNTE2NjdDNi40MzMzMyA4LjczODg5IDYuODg4ODkgOC4wNjExMSA3LjQ2NjY3IDcuNDgzMzNDOC4wNTU1NiA2Ljg5NDQ0IDguNzM4ODkgNi40MzMzMyA5LjUxNjY3IDYuMUMxMC4yOTQ0IDUuNzY2NjcgMTEuMTIyMiA1LjYgMTIgNS42QzEyLjg4ODkgNS42IDEzLjcxNjcgNS43NjY2NyAxNC40ODMzIDYuMUMxNS4yNjExIDYuNDMzMzMgMTUuOTM4OSA2Ljg5NDQ0IDE2LjUxNjcgNy40ODMzM0MxNy4xMDU2IDguMDYxMTEgMTcuNTY2NyA4LjczODg5IDE3LjkgOS41MTY2N0MxOC4yMzMzIDEwLjI4MzMgMTguNCAxMS4xMTExIDE4LjQgMTJDMTguNCAxMi44Nzc4IDE4LjIzMzMgMTMuNzA1NiAxNy45IDE0LjQ4MzNDMTcuNTY2NyAxNS4yNjExIDE3LjEwNTYgMTUuOTQ0NCAxNi41MTY3IDE2LjUzMzNDMTUuOTM4OSAxNy4xMTExIDE1LjI2MTEgMTcuNTY2NyAxNC40ODMzIDE3LjlDMTMuNzE2NyAxOC4yMzMzIDEyLjg4ODkgMTguNCAxMiAxOC40Wk0xMiAxNy4yQzEzLjQ0NDQgMTcuMiAxNC42NzIyIDE2LjY5NDQgMTUuNjgzMyAxNS42ODMzQzE2LjY5NDQgMTQuNjcyMiAxNy4yIDEzLjQ0NDQgMTcuMiAxMkMxNy4yIDEwLjU1NTYgMTYuNjk0NCA5LjMyNzc4IDE1LjY4MzMgOC4zMTY2N0MxNC42NzIyIDcuMzA1NTUgMTMuNDQ0NCA2LjggMTIgNi44QzEwLjU1NTYgNi44IDkuMzI3NzggNy4zMDU1NSA4LjMxNjY3IDguMzE2NjdDNy4zMDU1NiA5LjMyNzc4IDYuOCAxMC41NTU2IDYuOCAxMkM2LjggMTMuNDQ0NCA3LjMwNTU2IDE0LjY3MjIgOC4zMTY2NyAxNS42ODMzQzkuMzI3NzggMTYuNjk0NCAxMC41NTU2IDE3LjIgMTIgMTcuMlpcIiBmaWxsPVwiIzIxMjEyMVwiLz5cbjwvZz5cbjxkZWZzPlxuPGNsaXBQYXRoIGlkPVwiY2xpcDBfNjA4M18zNDgwNFwiPlxuPHJlY3Qgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgZmlsbD1cIndoaXRlXCIvPlxuPC9jbGlwUGF0aD5cbjwvZGVmcz5gO1xuICAgICAgZmlyZWJhc2VUZXh0LmlubmVyVGV4dCA9ICdQcmV2aWV3IGJhY2tlbmQgcnVubmluZyBpbiB0aGlzIHdvcmtzcGFjZS4nO1xuICAgIH1cbiAgICBmaXJlYmFzZVRleHQuc2V0QXR0cmlidXRlKCdpZCcsIGZpcmViYXNlVGV4dElkKTtcbiAgfVxuICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBzZXR1cERvbSk7XG4gIH0gZWxzZSB7XG4gICAgc2V0dXBEb20oKTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IENPTlNUQU5UUyB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IGdldERlZmF1bHRzIH0gZnJvbSAnLi9kZWZhdWx0cyc7XG5cbi8qKlxuICogVHlwZSBwbGFjZWhvbGRlciBmb3IgYFdvcmtlckdsb2JhbFNjb3BlYCBmcm9tIGB3ZWJ3b3JrZXJgXG4gKi9cbmRlY2xhcmUgY2xhc3MgV29ya2VyR2xvYmFsU2NvcGUge31cblxuLyoqXG4gKiBSZXR1cm5zIG5hdmlnYXRvci51c2VyQWdlbnQgc3RyaW5nIG9yICcnIGlmIGl0J3Mgbm90IGRlZmluZWQuXG4gKiBAcmV0dXJuIHVzZXIgYWdlbnQgc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRVQSgpOiBzdHJpbmcge1xuICBpZiAoXG4gICAgdHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICB0eXBlb2YgbmF2aWdhdG9yWyd1c2VyQWdlbnQnXSA9PT0gJ3N0cmluZydcbiAgKSB7XG4gICAgcmV0dXJuIG5hdmlnYXRvclsndXNlckFnZW50J107XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG59XG5cbi8qKlxuICogRGV0ZWN0IENvcmRvdmEgLyBQaG9uZUdhcCAvIElvbmljIGZyYW1ld29ya3Mgb24gYSBtb2JpbGUgZGV2aWNlLlxuICpcbiAqIERlbGliZXJhdGVseSBkb2VzIG5vdCByZWx5IG9uIGNoZWNraW5nIGBmaWxlOi8vYCBVUkxzIChhcyB0aGlzIGZhaWxzIFBob25lR2FwXG4gKiBpbiB0aGUgUmlwcGxlIGVtdWxhdG9yKSBub3IgQ29yZG92YSBgb25EZXZpY2VSZWFkeWAsIHdoaWNoIHdvdWxkIG5vcm1hbGx5XG4gKiB3YWl0IGZvciBhIGNhbGxiYWNrLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNNb2JpbGVDb3Jkb3ZhKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG4gICAgLy8gQHRzLWlnbm9yZSBTZXR0aW5nIHVwIGFuIGJyb2FkbHkgYXBwbGljYWJsZSBpbmRleCBzaWduYXR1cmUgZm9yIFdpbmRvd1xuICAgIC8vIGp1c3QgdG8gZGVhbCB3aXRoIHRoaXMgY2FzZSB3b3VsZCBwcm9iYWJseSBiZSBhIGJhZCBpZGVhLlxuICAgICEhKHdpbmRvd1snY29yZG92YSddIHx8IHdpbmRvd1sncGhvbmVnYXAnXSB8fCB3aW5kb3dbJ1Bob25lR2FwJ10pICYmXG4gICAgL2lvc3xpcGhvbmV8aXBvZHxpcGFkfGFuZHJvaWR8YmxhY2tiZXJyeXxpZW1vYmlsZS9pLnRlc3QoZ2V0VUEoKSlcbiAgKTtcbn1cblxuLyoqXG4gKiBEZXRlY3QgTm9kZS5qcy5cbiAqXG4gKiBAcmV0dXJuIHRydWUgaWYgTm9kZS5qcyBlbnZpcm9ubWVudCBpcyBkZXRlY3RlZCBvciBzcGVjaWZpZWQuXG4gKi9cbi8vIE5vZGUgZGV0ZWN0aW9uIGxvZ2ljIGZyb206IGh0dHBzOi8vZ2l0aHViLmNvbS9pbGlha2FuL2RldGVjdC1ub2RlL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTm9kZSgpOiBib29sZWFuIHtcbiAgY29uc3QgZm9yY2VFbnZpcm9ubWVudCA9IGdldERlZmF1bHRzKCk/LmZvcmNlRW52aXJvbm1lbnQ7XG4gIGlmIChmb3JjZUVudmlyb25tZW50ID09PSAnbm9kZScpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmIChmb3JjZUVudmlyb25tZW50ID09PSAnYnJvd3NlcicpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0cnkge1xuICAgIHJldHVybiAoXG4gICAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZ2xvYmFsLnByb2Nlc3MpID09PSAnW29iamVjdCBwcm9jZXNzXSdcbiAgICApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogRGV0ZWN0IEJyb3dzZXIgRW52aXJvbm1lbnQuXG4gKiBOb3RlOiBUaGlzIHdpbGwgcmV0dXJuIHRydWUgZm9yIGNlcnRhaW4gdGVzdCBmcmFtZXdvcmtzIHRoYXQgYXJlIGluY29tcGxldGVseVxuICogbWltaWNraW5nIGEgYnJvd3NlciwgYW5kIHNob3VsZCBub3QgbGVhZCB0byBhc3N1bWluZyBhbGwgYnJvd3NlciBBUElzIGFyZVxuICogYXZhaWxhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCcm93c2VyKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgfHwgaXNXZWJXb3JrZXIoKTtcbn1cblxuLyoqXG4gKiBEZXRlY3QgV2ViIFdvcmtlciBjb250ZXh0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXZWJXb3JrZXIoKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIFdvcmtlckdsb2JhbFNjb3BlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIHNlbGYgaW5zdGFuY2VvZiBXb3JrZXJHbG9iYWxTY29wZVxuICApO1xufVxuXG4vKipcbiAqIERldGVjdCBDbG91ZGZsYXJlIFdvcmtlciBjb250ZXh0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDbG91ZGZsYXJlV29ya2VyKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmXG4gICAgbmF2aWdhdG9yLnVzZXJBZ2VudCA9PT0gJ0Nsb3VkZmxhcmUtV29ya2VycydcbiAgKTtcbn1cblxuLyoqXG4gKiBEZXRlY3QgYnJvd3NlciBleHRlbnNpb25zIChDaHJvbWUgYW5kIEZpcmVmb3ggYXQgbGVhc3QpLlxuICovXG5pbnRlcmZhY2UgQnJvd3NlclJ1bnRpbWUge1xuICBpZD86IHVua25vd247XG59XG5kZWNsYXJlIGNvbnN0IGNocm9tZTogeyBydW50aW1lPzogQnJvd3NlclJ1bnRpbWUgfTtcbmRlY2xhcmUgY29uc3QgYnJvd3NlcjogeyBydW50aW1lPzogQnJvd3NlclJ1bnRpbWUgfTtcbmV4cG9ydCBmdW5jdGlvbiBpc0Jyb3dzZXJFeHRlbnNpb24oKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJ1bnRpbWUgPVxuICAgIHR5cGVvZiBjaHJvbWUgPT09ICdvYmplY3QnXG4gICAgICA/IGNocm9tZS5ydW50aW1lXG4gICAgICA6IHR5cGVvZiBicm93c2VyID09PSAnb2JqZWN0J1xuICAgICAgPyBicm93c2VyLnJ1bnRpbWVcbiAgICAgIDogdW5kZWZpbmVkO1xuICByZXR1cm4gdHlwZW9mIHJ1bnRpbWUgPT09ICdvYmplY3QnICYmIHJ1bnRpbWUuaWQgIT09IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBEZXRlY3QgUmVhY3QgTmF0aXZlLlxuICpcbiAqIEByZXR1cm4gdHJ1ZSBpZiBSZWFjdE5hdGl2ZSBlbnZpcm9ubWVudCBpcyBkZXRlY3RlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUmVhY3ROYXRpdmUoKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIG5hdmlnYXRvciA9PT0gJ29iamVjdCcgJiYgbmF2aWdhdG9yWydwcm9kdWN0J10gPT09ICdSZWFjdE5hdGl2ZSdcbiAgKTtcbn1cblxuLyoqIERldGVjdHMgRWxlY3Ryb24gYXBwcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VsZWN0cm9uKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0VUEoKS5pbmRleE9mKCdFbGVjdHJvbi8nKSA+PSAwO1xufVxuXG4vKiogRGV0ZWN0cyBJbnRlcm5ldCBFeHBsb3Jlci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0lFKCk6IGJvb2xlYW4ge1xuICBjb25zdCB1YSA9IGdldFVBKCk7XG4gIHJldHVybiB1YS5pbmRleE9mKCdNU0lFICcpID49IDAgfHwgdWEuaW5kZXhPZignVHJpZGVudC8nKSA+PSAwO1xufVxuXG4vKiogRGV0ZWN0cyBVbml2ZXJzYWwgV2luZG93cyBQbGF0Zm9ybSBhcHBzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVVdQKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0VUEoKS5pbmRleE9mKCdNU0FwcEhvc3QvJykgPj0gMDtcbn1cblxuLyoqXG4gKiBEZXRlY3Qgd2hldGhlciB0aGUgY3VycmVudCBTREsgYnVpbGQgaXMgdGhlIE5vZGUgdmVyc2lvbi5cbiAqXG4gKiBAcmV0dXJuIHRydWUgaWYgaXQncyB0aGUgTm9kZSBTREsgYnVpbGQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc05vZGVTZGsoKTogYm9vbGVhbiB7XG4gIHJldHVybiBDT05TVEFOVFMuTk9ERV9DTElFTlQgPT09IHRydWUgfHwgQ09OU1RBTlRTLk5PREVfQURNSU4gPT09IHRydWU7XG59XG5cbi8qKiBSZXR1cm5zIHRydWUgaWYgd2UgYXJlIHJ1bm5pbmcgaW4gU2FmYXJpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2FmYXJpKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgICFpc05vZGUoKSAmJlxuICAgICEhbmF2aWdhdG9yLnVzZXJBZ2VudCAmJlxuICAgIG5hdmlnYXRvci51c2VyQWdlbnQuaW5jbHVkZXMoJ1NhZmFyaScpICYmXG4gICAgIW5hdmlnYXRvci51c2VyQWdlbnQuaW5jbHVkZXMoJ0Nocm9tZScpXG4gICk7XG59XG5cbi8qKiBSZXR1cm5zIHRydWUgaWYgd2UgYXJlIHJ1bm5pbmcgaW4gU2FmYXJpIG9yIFdlYktpdCAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2FmYXJpT3JXZWJraXQoKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgIWlzTm9kZSgpICYmXG4gICAgISFuYXZpZ2F0b3IudXNlckFnZW50ICYmXG4gICAgKG5hdmlnYXRvci51c2VyQWdlbnQuaW5jbHVkZXMoJ1NhZmFyaScpIHx8XG4gICAgICBuYXZpZ2F0b3IudXNlckFnZW50LmluY2x1ZGVzKCdXZWJLaXQnKSkgJiZcbiAgICAhbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmNsdWRlcygnQ2hyb21lJylcbiAgKTtcbn1cblxuLyoqXG4gKiBUaGlzIG1ldGhvZCBjaGVja3MgaWYgaW5kZXhlZERCIGlzIHN1cHBvcnRlZCBieSBjdXJyZW50IGJyb3dzZXIvc2VydmljZSB3b3JrZXIgY29udGV4dFxuICogQHJldHVybiB0cnVlIGlmIGluZGV4ZWREQiBpcyBzdXBwb3J0ZWQgYnkgY3VycmVudCBicm93c2VyL3NlcnZpY2Ugd29ya2VyIGNvbnRleHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzSW5kZXhlZERCQXZhaWxhYmxlKCk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIHJldHVybiB0eXBlb2YgaW5kZXhlZERCID09PSAnb2JqZWN0JztcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHZhbGlkYXRlcyBicm93c2VyL3N3IGNvbnRleHQgZm9yIGluZGV4ZWREQiBieSBvcGVuaW5nIGEgZHVtbXkgaW5kZXhlZERCIGRhdGFiYXNlIGFuZCByZWplY3RcbiAqIGlmIGVycm9ycyBvY2N1ciBkdXJpbmcgdGhlIGRhdGFiYXNlIG9wZW4gb3BlcmF0aW9uLlxuICpcbiAqIEB0aHJvd3MgZXhjZXB0aW9uIGlmIGN1cnJlbnQgYnJvd3Nlci9zdyBjb250ZXh0IGNhbid0IHJ1biBpZGIub3BlbiAoZXg6IFNhZmFyaSBpZnJhbWUsIEZpcmVmb3hcbiAqIHByaXZhdGUgYnJvd3NpbmcpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUluZGV4ZWREQk9wZW5hYmxlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcHJlRXhpc3Q6IGJvb2xlYW4gPSB0cnVlO1xuICAgICAgY29uc3QgREJfQ0hFQ0tfTkFNRSA9XG4gICAgICAgICd2YWxpZGF0ZS1icm93c2VyLWNvbnRleHQtZm9yLWluZGV4ZWRkYi1hbmFseXRpY3MtbW9kdWxlJztcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBzZWxmLmluZGV4ZWREQi5vcGVuKERCX0NIRUNLX05BTUUpO1xuICAgICAgcmVxdWVzdC5vbnN1Y2Nlc3MgPSAoKSA9PiB7XG4gICAgICAgIHJlcXVlc3QucmVzdWx0LmNsb3NlKCk7XG4gICAgICAgIC8vIGRlbGV0ZSBkYXRhYmFzZSBvbmx5IHdoZW4gaXQgZG9lc24ndCBwcmUtZXhpc3RcbiAgICAgICAgaWYgKCFwcmVFeGlzdCkge1xuICAgICAgICAgIHNlbGYuaW5kZXhlZERCLmRlbGV0ZURhdGFiYXNlKERCX0NIRUNLX05BTUUpO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICB9O1xuICAgICAgcmVxdWVzdC5vbnVwZ3JhZGVuZWVkZWQgPSAoKSA9PiB7XG4gICAgICAgIHByZUV4aXN0ID0gZmFsc2U7XG4gICAgICB9O1xuXG4gICAgICByZXF1ZXN0Lm9uZXJyb3IgPSAoKSA9PiB7XG4gICAgICAgIHJlamVjdChyZXF1ZXN0LmVycm9yPy5tZXNzYWdlIHx8ICcnKTtcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJlamVjdChlcnJvcik7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqXG4gKlxuICogVGhpcyBtZXRob2QgY2hlY2tzIHdoZXRoZXIgY29va2llIGlzIGVuYWJsZWQgd2l0aGluIGN1cnJlbnQgYnJvd3NlclxuICogQHJldHVybiB0cnVlIGlmIGNvb2tpZSBpcyBlbmFibGVkIHdpdGhpbiBjdXJyZW50IGJyb3dzZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFyZUNvb2tpZXNFbmFibGVkKCk6IGJvb2xlYW4ge1xuICBpZiAodHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgfHwgIW5hdmlnYXRvci5jb29raWVFbmFibGVkKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgU3RhbmRhcmRpemVkIEZpcmViYXNlIEVycm9yLlxuICpcbiAqIFVzYWdlOlxuICpcbiAqICAgLy8gVHlwZVNjcmlwdCBzdHJpbmcgbGl0ZXJhbHMgZm9yIHR5cGUtc2FmZSBjb2Rlc1xuICogICB0eXBlIEVyciA9XG4gKiAgICAgJ3Vua25vd24nIHxcbiAqICAgICAnb2JqZWN0LW5vdC1mb3VuZCdcbiAqICAgICA7XG4gKlxuICogICAvLyBDbG9zdXJlIGVudW0gZm9yIHR5cGUtc2FmZSBlcnJvciBjb2Rlc1xuICogICAvLyBhdC1lbnVtIHtzdHJpbmd9XG4gKiAgIHZhciBFcnIgPSB7XG4gKiAgICAgVU5LTk9XTjogJ3Vua25vd24nLFxuICogICAgIE9CSkVDVF9OT1RfRk9VTkQ6ICdvYmplY3Qtbm90LWZvdW5kJyxcbiAqICAgfVxuICpcbiAqICAgbGV0IGVycm9yczogTWFwPEVyciwgc3RyaW5nPiA9IHtcbiAqICAgICAnZ2VuZXJpYy1lcnJvcic6IFwiVW5rbm93biBlcnJvclwiLFxuICogICAgICdmaWxlLW5vdC1mb3VuZCc6IFwiQ291bGQgbm90IGZpbmQgZmlsZTogeyRmaWxlfVwiLFxuICogICB9O1xuICpcbiAqICAgLy8gVHlwZS1zYWZlIGZ1bmN0aW9uIC0gbXVzdCBwYXNzIGEgdmFsaWQgZXJyb3IgY29kZSBhcyBwYXJhbS5cbiAqICAgbGV0IGVycm9yID0gbmV3IEVycm9yRmFjdG9yeTxFcnI+KCdzZXJ2aWNlJywgJ1NlcnZpY2UnLCBlcnJvcnMpO1xuICpcbiAqICAgLi4uXG4gKiAgIHRocm93IGVycm9yLmNyZWF0ZShFcnIuR0VORVJJQyk7XG4gKiAgIC4uLlxuICogICB0aHJvdyBlcnJvci5jcmVhdGUoRXJyLkZJTEVfTk9UX0ZPVU5ELCB7J2ZpbGUnOiBmaWxlTmFtZX0pO1xuICogICAuLi5cbiAqICAgLy8gU2VydmljZTogQ291bGQgbm90IGZpbGUgZmlsZTogZm9vLnR4dCAoc2VydmljZS9maWxlLW5vdC1mb3VuZCkuXG4gKlxuICogICBjYXRjaCAoZSkge1xuICogICAgIGFzc2VydChlLm1lc3NhZ2UgPT09IFwiQ291bGQgbm90IGZpbmQgZmlsZTogZm9vLnR4dC5cIik7XG4gKiAgICAgaWYgKChlIGFzIEZpcmViYXNlRXJyb3IpPy5jb2RlID09PSAnc2VydmljZS9maWxlLW5vdC1mb3VuZCcpIHtcbiAqICAgICAgIGNvbnNvbGUubG9nKFwiQ291bGQgbm90IHJlYWQgZmlsZTogXCIgKyBlWydmaWxlJ10pO1xuICogICAgIH1cbiAqICAgfVxuICovXG5cbmV4cG9ydCB0eXBlIEVycm9yTWFwPEVycm9yQ29kZSBleHRlbmRzIHN0cmluZz4gPSB7XG4gIHJlYWRvbmx5IFtLIGluIEVycm9yQ29kZV06IHN0cmluZztcbn07XG5cbmNvbnN0IEVSUk9SX05BTUUgPSAnRmlyZWJhc2VFcnJvcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RyaW5nTGlrZSB7XG4gIHRvU3RyaW5nKCk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFcnJvckRhdGEge1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xufVxuXG4vLyBCYXNlZCBvbiBjb2RlIGZyb206XG4vLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9FcnJvciNDdXN0b21fRXJyb3JfVHlwZXNcbmV4cG9ydCBjbGFzcyBGaXJlYmFzZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAvKiogVGhlIGN1c3RvbSBuYW1lIGZvciBhbGwgRmlyZWJhc2VFcnJvcnMuICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZyA9IEVSUk9SX05BTUU7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgLyoqIFRoZSBlcnJvciBjb2RlIGZvciB0aGlzIGVycm9yLiAqL1xuICAgIHJlYWRvbmx5IGNvZGU6IHN0cmluZyxcbiAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgLyoqIEN1c3RvbSBkYXRhIGZvciB0aGlzIGVycm9yLiAqL1xuICAgIHB1YmxpYyBjdXN0b21EYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAvLyBGaXggRm9yIEVTNVxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9NaWNyb3NvZnQvVHlwZVNjcmlwdC13aWtpL2Jsb2IvbWFzdGVyL0JyZWFraW5nLUNoYW5nZXMubWQjZXh0ZW5kaW5nLWJ1aWx0LWlucy1saWtlLWVycm9yLWFycmF5LWFuZC1tYXAtbWF5LW5vLWxvbmdlci13b3JrXG4gICAgLy8gVE9ETyhkbGFyb2NxdWUpOiBSZXBsYWNlIHRoaXMgd2l0aCBgbmV3LnRhcmdldGA6IGh0dHBzOi8vd3d3LnR5cGVzY3JpcHRsYW5nLm9yZy9kb2NzL2hhbmRib29rL3JlbGVhc2Utbm90ZXMvdHlwZXNjcmlwdC0yLTIuaHRtbCNzdXBwb3J0LWZvci1uZXd0YXJnZXRcbiAgICAvLyAgICAgICAgICAgICAgICAgICB3aGljaCB3ZSBjYW4gbm93IHVzZSBzaW5jZSB3ZSBubyBsb25nZXIgdGFyZ2V0IEVTNS5cbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgRmlyZWJhc2VFcnJvci5wcm90b3R5cGUpO1xuXG4gICAgLy8gTWFpbnRhaW5zIHByb3BlciBzdGFjayB0cmFjZSBmb3Igd2hlcmUgb3VyIGVycm9yIHdhcyB0aHJvd24uXG4gICAgLy8gT25seSBhdmFpbGFibGUgb24gVjguXG4gICAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBFcnJvckZhY3RvcnkucHJvdG90eXBlLmNyZWF0ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBFcnJvckZhY3Rvcnk8XG4gIEVycm9yQ29kZSBleHRlbmRzIHN0cmluZyxcbiAgRXJyb3JQYXJhbXMgZXh0ZW5kcyB7IHJlYWRvbmx5IFtLIGluIEVycm9yQ29kZV0/OiBFcnJvckRhdGEgfSA9IHt9XG4+IHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlTmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZXJyb3JzOiBFcnJvck1hcDxFcnJvckNvZGU+XG4gICkge31cblxuICBjcmVhdGU8SyBleHRlbmRzIEVycm9yQ29kZT4oXG4gICAgY29kZTogSyxcbiAgICAuLi5kYXRhOiBLIGV4dGVuZHMga2V5b2YgRXJyb3JQYXJhbXMgPyBbRXJyb3JQYXJhbXNbS11dIDogW11cbiAgKTogRmlyZWJhc2VFcnJvciB7XG4gICAgY29uc3QgY3VzdG9tRGF0YSA9IChkYXRhWzBdIGFzIEVycm9yRGF0YSkgfHwge307XG4gICAgY29uc3QgZnVsbENvZGUgPSBgJHt0aGlzLnNlcnZpY2V9LyR7Y29kZX1gO1xuICAgIGNvbnN0IHRlbXBsYXRlID0gdGhpcy5lcnJvcnNbY29kZV07XG5cbiAgICBjb25zdCBtZXNzYWdlID0gdGVtcGxhdGUgPyByZXBsYWNlVGVtcGxhdGUodGVtcGxhdGUsIGN1c3RvbURhdGEpIDogJ0Vycm9yJztcbiAgICAvLyBTZXJ2aWNlIE5hbWU6IEVycm9yIG1lc3NhZ2UgKHNlcnZpY2UvY29kZSkuXG4gICAgY29uc3QgZnVsbE1lc3NhZ2UgPSBgJHt0aGlzLnNlcnZpY2VOYW1lfTogJHttZXNzYWdlfSAoJHtmdWxsQ29kZX0pLmA7XG5cbiAgICBjb25zdCBlcnJvciA9IG5ldyBGaXJlYmFzZUVycm9yKGZ1bGxDb2RlLCBmdWxsTWVzc2FnZSwgY3VzdG9tRGF0YSk7XG5cbiAgICByZXR1cm4gZXJyb3I7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVwbGFjZVRlbXBsYXRlKHRlbXBsYXRlOiBzdHJpbmcsIGRhdGE6IEVycm9yRGF0YSk6IHN0cmluZyB7XG4gIHJldHVybiB0ZW1wbGF0ZS5yZXBsYWNlKFBBVFRFUk4sIChfLCBrZXkpID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IGRhdGFba2V5XTtcbiAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCA/IFN0cmluZyh2YWx1ZSkgOiBgPCR7a2V5fT8+YDtcbiAgfSk7XG59XG5cbmNvbnN0IFBBVFRFUk4gPSAvXFx7XFwkKFtefV0rKX0vZztcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKipcbiAqIEV2YWx1YXRlcyBhIEpTT04gc3RyaW5nIGludG8gYSBqYXZhc2NyaXB0IG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIEEgc3RyaW5nIGNvbnRhaW5pbmcgSlNPTi5cbiAqIEByZXR1cm4geyp9IFRoZSBqYXZhc2NyaXB0IG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHNwZWNpZmllZCBKU09OLlxuICovXG5leHBvcnQgZnVuY3Rpb24ganNvbkV2YWwoc3RyOiBzdHJpbmcpOiB1bmtub3duIHtcbiAgcmV0dXJuIEpTT04ucGFyc2Uoc3RyKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIEpTT04gcmVwcmVzZW50aW5nIGEgamF2YXNjcmlwdCBvYmplY3QuXG4gKiBAcGFyYW0geyp9IGRhdGEgSmF2YVNjcmlwdCBvYmplY3QgdG8gYmUgc3RyaW5naWZpZWQuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBKU09OIGNvbnRlbnRzIG9mIHRoZSBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpbmdpZnkoZGF0YTogdW5rbm93bik6IHN0cmluZyB7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShkYXRhKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBiYXNlNjREZWNvZGUgfSBmcm9tICcuL2NyeXB0JztcbmltcG9ydCB7IGpzb25FdmFsIH0gZnJvbSAnLi9qc29uJztcblxuaW50ZXJmYWNlIENsYWltcyB7XG4gIFtrZXk6IHN0cmluZ106IHt9O1xufVxuXG5pbnRlcmZhY2UgRGVjb2RlZFRva2VuIHtcbiAgaGVhZGVyOiBvYmplY3Q7XG4gIGNsYWltczogQ2xhaW1zO1xuICBkYXRhOiBvYmplY3Q7XG4gIHNpZ25hdHVyZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIERlY29kZXMgYSBGaXJlYmFzZSBhdXRoLiB0b2tlbiBpbnRvIGNvbnN0aXR1ZW50IHBhcnRzLlxuICpcbiAqIE5vdGVzOlxuICogLSBNYXkgcmV0dXJuIHdpdGggaW52YWxpZCAvIGluY29tcGxldGUgY2xhaW1zIGlmIHRoZXJlJ3Mgbm8gbmF0aXZlIGJhc2U2NCBkZWNvZGluZyBzdXBwb3J0LlxuICogLSBEb2Vzbid0IGNoZWNrIGlmIHRoZSB0b2tlbiBpcyBhY3R1YWxseSB2YWxpZC5cbiAqL1xuZXhwb3J0IGNvbnN0IGRlY29kZSA9IGZ1bmN0aW9uICh0b2tlbjogc3RyaW5nKTogRGVjb2RlZFRva2VuIHtcbiAgbGV0IGhlYWRlciA9IHt9LFxuICAgIGNsYWltczogQ2xhaW1zID0ge30sXG4gICAgZGF0YSA9IHt9LFxuICAgIHNpZ25hdHVyZSA9ICcnO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcGFydHMgPSB0b2tlbi5zcGxpdCgnLicpO1xuICAgIGhlYWRlciA9IGpzb25FdmFsKGJhc2U2NERlY29kZShwYXJ0c1swXSkgfHwgJycpIGFzIG9iamVjdDtcbiAgICBjbGFpbXMgPSBqc29uRXZhbChiYXNlNjREZWNvZGUocGFydHNbMV0pIHx8ICcnKSBhcyBDbGFpbXM7XG4gICAgc2lnbmF0dXJlID0gcGFydHNbMl07XG4gICAgZGF0YSA9IGNsYWltc1snZCddIHx8IHt9O1xuICAgIGRlbGV0ZSBjbGFpbXNbJ2QnXTtcbiAgfSBjYXRjaCAoZSkge31cblxuICByZXR1cm4ge1xuICAgIGhlYWRlcixcbiAgICBjbGFpbXMsXG4gICAgZGF0YSxcbiAgICBzaWduYXR1cmVcbiAgfTtcbn07XG5cbmludGVyZmFjZSBEZWNvZGVkVG9rZW4ge1xuICBoZWFkZXI6IG9iamVjdDtcbiAgY2xhaW1zOiBDbGFpbXM7XG4gIGRhdGE6IG9iamVjdDtcbiAgc2lnbmF0dXJlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVjb2RlcyBhIEZpcmViYXNlIGF1dGguIHRva2VuIGFuZCBjaGVja3MgdGhlIHZhbGlkaXR5IG9mIGl0cyB0aW1lLWJhc2VkIGNsYWltcy4gV2lsbCByZXR1cm4gdHJ1ZSBpZiB0aGVcbiAqIHRva2VuIGlzIHdpdGhpbiB0aGUgdGltZSB3aW5kb3cgYXV0aG9yaXplZCBieSB0aGUgJ25iZicgKG5vdC1iZWZvcmUpIGFuZCAnaWF0JyAoaXNzdWVkLWF0KSBjbGFpbXMuXG4gKlxuICogTm90ZXM6XG4gKiAtIE1heSByZXR1cm4gYSBmYWxzZSBuZWdhdGl2ZSBpZiB0aGVyZSdzIG5vIG5hdGl2ZSBiYXNlNjQgZGVjb2Rpbmcgc3VwcG9ydC5cbiAqIC0gRG9lc24ndCBjaGVjayBpZiB0aGUgdG9rZW4gaXMgYWN0dWFsbHkgdmFsaWQuXG4gKi9cbmV4cG9ydCBjb25zdCBpc1ZhbGlkVGltZXN0YW1wID0gZnVuY3Rpb24gKHRva2VuOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgY2xhaW1zOiBDbGFpbXMgPSBkZWNvZGUodG9rZW4pLmNsYWltcztcbiAgY29uc3Qgbm93OiBudW1iZXIgPSBNYXRoLmZsb29yKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gIGxldCB2YWxpZFNpbmNlOiBudW1iZXIgPSAwLFxuICAgIHZhbGlkVW50aWw6IG51bWJlciA9IDA7XG5cbiAgaWYgKHR5cGVvZiBjbGFpbXMgPT09ICdvYmplY3QnKSB7XG4gICAgaWYgKGNsYWltcy5oYXNPd25Qcm9wZXJ0eSgnbmJmJykpIHtcbiAgICAgIHZhbGlkU2luY2UgPSBjbGFpbXNbJ25iZiddIGFzIG51bWJlcjtcbiAgICB9IGVsc2UgaWYgKGNsYWltcy5oYXNPd25Qcm9wZXJ0eSgnaWF0JykpIHtcbiAgICAgIHZhbGlkU2luY2UgPSBjbGFpbXNbJ2lhdCddIGFzIG51bWJlcjtcbiAgICB9XG5cbiAgICBpZiAoY2xhaW1zLmhhc093blByb3BlcnR5KCdleHAnKSkge1xuICAgICAgdmFsaWRVbnRpbCA9IGNsYWltc1snZXhwJ10gYXMgbnVtYmVyO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyB0b2tlbiB3aWxsIGV4cGlyZSBhZnRlciAyNGggYnkgZGVmYXVsdFxuICAgICAgdmFsaWRVbnRpbCA9IHZhbGlkU2luY2UgKyA4NjQwMDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gKFxuICAgICEhbm93ICYmXG4gICAgISF2YWxpZFNpbmNlICYmXG4gICAgISF2YWxpZFVudGlsICYmXG4gICAgbm93ID49IHZhbGlkU2luY2UgJiZcbiAgICBub3cgPD0gdmFsaWRVbnRpbFxuICApO1xufTtcblxuLyoqXG4gKiBEZWNvZGVzIGEgRmlyZWJhc2UgYXV0aC4gdG9rZW4gYW5kIHJldHVybnMgaXRzIGlzc3VlZCBhdCB0aW1lIGlmIHZhbGlkLCBudWxsIG90aGVyd2lzZS5cbiAqXG4gKiBOb3RlczpcbiAqIC0gTWF5IHJldHVybiBudWxsIGlmIHRoZXJlJ3Mgbm8gbmF0aXZlIGJhc2U2NCBkZWNvZGluZyBzdXBwb3J0LlxuICogLSBEb2Vzbid0IGNoZWNrIGlmIHRoZSB0b2tlbiBpcyBhY3R1YWxseSB2YWxpZC5cbiAqL1xuZXhwb3J0IGNvbnN0IGlzc3VlZEF0VGltZSA9IGZ1bmN0aW9uICh0b2tlbjogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gIGNvbnN0IGNsYWltczogQ2xhaW1zID0gZGVjb2RlKHRva2VuKS5jbGFpbXM7XG4gIGlmICh0eXBlb2YgY2xhaW1zID09PSAnb2JqZWN0JyAmJiBjbGFpbXMuaGFzT3duUHJvcGVydHkoJ2lhdCcpKSB7XG4gICAgcmV0dXJuIGNsYWltc1snaWF0J10gYXMgbnVtYmVyO1xuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuLyoqXG4gKiBEZWNvZGVzIGEgRmlyZWJhc2UgYXV0aC4gdG9rZW4gYW5kIGNoZWNrcyB0aGUgdmFsaWRpdHkgb2YgaXRzIGZvcm1hdC4gRXhwZWN0cyBhIHZhbGlkIGlzc3VlZC1hdCB0aW1lLlxuICpcbiAqIE5vdGVzOlxuICogLSBNYXkgcmV0dXJuIGEgZmFsc2UgbmVnYXRpdmUgaWYgdGhlcmUncyBubyBuYXRpdmUgYmFzZTY0IGRlY29kaW5nIHN1cHBvcnQuXG4gKiAtIERvZXNuJ3QgY2hlY2sgaWYgdGhlIHRva2VuIGlzIGFjdHVhbGx5IHZhbGlkLlxuICovXG5leHBvcnQgY29uc3QgaXNWYWxpZEZvcm1hdCA9IGZ1bmN0aW9uICh0b2tlbjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGRlY29kZWQgPSBkZWNvZGUodG9rZW4pLFxuICAgIGNsYWltcyA9IGRlY29kZWQuY2xhaW1zO1xuXG4gIHJldHVybiAhIWNsYWltcyAmJiB0eXBlb2YgY2xhaW1zID09PSAnb2JqZWN0JyAmJiBjbGFpbXMuaGFzT3duUHJvcGVydHkoJ2lhdCcpO1xufTtcblxuLyoqXG4gKiBBdHRlbXB0cyB0byBwZWVyIGludG8gYW4gYXV0aCB0b2tlbiBhbmQgZGV0ZXJtaW5lIGlmIGl0J3MgYW4gYWRtaW4gYXV0aCB0b2tlbiBieSBsb29raW5nIGF0IHRoZSBjbGFpbXMgcG9ydGlvbi5cbiAqXG4gKiBOb3RlczpcbiAqIC0gTWF5IHJldHVybiBhIGZhbHNlIG5lZ2F0aXZlIGlmIHRoZXJlJ3Mgbm8gbmF0aXZlIGJhc2U2NCBkZWNvZGluZyBzdXBwb3J0LlxuICogLSBEb2Vzbid0IGNoZWNrIGlmIHRoZSB0b2tlbiBpcyBhY3R1YWxseSB2YWxpZC5cbiAqL1xuZXhwb3J0IGNvbnN0IGlzQWRtaW4gPSBmdW5jdGlvbiAodG9rZW46IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBjbGFpbXM6IENsYWltcyA9IGRlY29kZSh0b2tlbikuY2xhaW1zO1xuICByZXR1cm4gdHlwZW9mIGNsYWltcyA9PT0gJ29iamVjdCcgJiYgY2xhaW1zWydhZG1pbiddID09PSB0cnVlO1xufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnM8VCBleHRlbmRzIG9iamVjdD4ob2JqOiBULCBrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhZmVHZXQ8VCBleHRlbmRzIG9iamVjdCwgSyBleHRlbmRzIGtleW9mIFQ+KFxuICBvYmo6IFQsXG4gIGtleTogS1xuKTogVFtLXSB8IHVuZGVmaW5lZCB7XG4gIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgcmV0dXJuIG9ialtrZXldO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRW1wdHkob2JqOiBvYmplY3QpOiBvYmogaXMge30ge1xuICBmb3IgKGNvbnN0IGtleSBpbiBvYmopIHtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1hcDxLIGV4dGVuZHMgc3RyaW5nLCBWLCBVPihcbiAgb2JqOiB7IFtrZXkgaW4gS106IFYgfSxcbiAgZm46ICh2YWx1ZTogViwga2V5OiBLLCBvYmo6IHsgW2tleSBpbiBLXTogViB9KSA9PiBVLFxuICBjb250ZXh0T2JqPzogdW5rbm93blxuKTogeyBba2V5IGluIEtdOiBVIH0ge1xuICBjb25zdCByZXM6IFBhcnRpYWw8eyBba2V5IGluIEtdOiBVIH0+ID0ge307XG4gIGZvciAoY29uc3Qga2V5IGluIG9iaikge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICByZXNba2V5XSA9IGZuLmNhbGwoY29udGV4dE9iaiwgb2JqW2tleV0sIGtleSwgb2JqKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlcyBhcyB7IFtrZXkgaW4gS106IFUgfTtcbn1cblxuLyoqXG4gKiBEZWVwIGVxdWFsIHR3byBvYmplY3RzLiBTdXBwb3J0IEFycmF5cyBhbmQgT2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBFcXVhbChhOiBvYmplY3QsIGI6IG9iamVjdCk6IGJvb2xlYW4ge1xuICBpZiAoYSA9PT0gYikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKTtcbiAgY29uc3QgYktleXMgPSBPYmplY3Qua2V5cyhiKTtcbiAgZm9yIChjb25zdCBrIG9mIGFLZXlzKSB7XG4gICAgaWYgKCFiS2V5cy5pbmNsdWRlcyhrKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGFQcm9wID0gKGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2tdO1xuICAgIGNvbnN0IGJQcm9wID0gKGIgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2tdO1xuICAgIGlmIChpc09iamVjdChhUHJvcCkgJiYgaXNPYmplY3QoYlByb3ApKSB7XG4gICAgICBpZiAoIWRlZXBFcXVhbChhUHJvcCwgYlByb3ApKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGFQcm9wICE9PSBiUHJvcCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgayBvZiBiS2V5cykge1xuICAgIGlmICghYUtleXMuaW5jbHVkZXMoaykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KHRoaW5nOiB1bmtub3duKTogdGhpbmcgaXMgb2JqZWN0IHtcbiAgcmV0dXJuIHRoaW5nICE9PSBudWxsICYmIHR5cGVvZiB0aGluZyA9PT0gJ29iamVjdCc7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRGVmZXJyZWQgfSBmcm9tICcuL2RlZmVycmVkJztcblxuLyoqXG4gKiBSZWplY3RzIGlmIHRoZSBnaXZlbiBwcm9taXNlIGRvZXNuJ3QgcmVzb2x2ZSBpbiB0aW1lSW5NUyBtaWxsaXNlY29uZHMuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb21pc2VXaXRoVGltZW91dDxUPihcbiAgcHJvbWlzZTogUHJvbWlzZTxUPixcbiAgdGltZUluTVMgPSAyMDAwXG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgZGVmZXJyZWRQcm9taXNlID0gbmV3IERlZmVycmVkPFQ+KCk7XG4gIHNldFRpbWVvdXQoKCkgPT4gZGVmZXJyZWRQcm9taXNlLnJlamVjdCgndGltZW91dCEnKSwgdGltZUluTVMpO1xuICBwcm9taXNlLnRoZW4oZGVmZXJyZWRQcm9taXNlLnJlc29sdmUsIGRlZmVycmVkUHJvbWlzZS5yZWplY3QpO1xuICByZXR1cm4gZGVmZXJyZWRQcm9taXNlLnByb21pc2U7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBSZXR1cm5zIGEgcXVlcnlzdHJpbmctZm9ybWF0dGVkIHN0cmluZyAoZS5nLiAmYXJnPXZhbCZhcmcyPXZhbDIpIGZyb20gYVxuICogcGFyYW1zIG9iamVjdCAoZS5nLiB7YXJnOiAndmFsJywgYXJnMjogJ3ZhbDInfSlcbiAqIE5vdGU6IFlvdSBtdXN0IHByZXBlbmQgaXQgd2l0aCA/IHdoZW4gYWRkaW5nIGl0IHRvIGEgVVJMLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcXVlcnlzdHJpbmcocXVlcnlzdHJpbmdQYXJhbXM6IHtcbiAgW2tleTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyO1xufSk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcmFtcyA9IFtdO1xuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhxdWVyeXN0cmluZ1BhcmFtcykpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHZhbHVlLmZvckVhY2goYXJyYXlWYWwgPT4ge1xuICAgICAgICBwYXJhbXMucHVzaChcbiAgICAgICAgICBlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChhcnJheVZhbClcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBwYXJhbXMucHVzaChlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcGFyYW1zLmxlbmd0aCA/ICcmJyArIHBhcmFtcy5qb2luKCcmJykgOiAnJztcbn1cblxuLyoqXG4gKiBEZWNvZGVzIGEgcXVlcnlzdHJpbmcgKGUuZy4gP2FyZz12YWwmYXJnMj12YWwyKSBpbnRvIGEgcGFyYW1zIG9iamVjdFxuICogKGUuZy4ge2FyZzogJ3ZhbCcsIGFyZzI6ICd2YWwyJ30pXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBxdWVyeXN0cmluZ0RlY29kZShxdWVyeXN0cmluZzogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IG9iajogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBjb25zdCB0b2tlbnMgPSBxdWVyeXN0cmluZy5yZXBsYWNlKC9eXFw/LywgJycpLnNwbGl0KCcmJyk7XG5cbiAgdG9rZW5zLmZvckVhY2godG9rZW4gPT4ge1xuICAgIGlmICh0b2tlbikge1xuICAgICAgY29uc3QgW2tleSwgdmFsdWVdID0gdG9rZW4uc3BsaXQoJz0nKTtcbiAgICAgIG9ialtkZWNvZGVVUklDb21wb25lbnQoa2V5KV0gPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvYmo7XG59XG5cbi8qKlxuICogRXh0cmFjdCB0aGUgcXVlcnkgc3RyaW5nIHBhcnQgb2YgYSBVUkwsIGluY2x1ZGluZyB0aGUgbGVhZGluZyBxdWVzdGlvbiBtYXJrIChpZiBwcmVzZW50KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RRdWVyeXN0cmluZyh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHF1ZXJ5U3RhcnQgPSB1cmwuaW5kZXhPZignPycpO1xuICBpZiAoIXF1ZXJ5U3RhcnQpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbiAgY29uc3QgZnJhZ21lbnRTdGFydCA9IHVybC5pbmRleE9mKCcjJywgcXVlcnlTdGFydCk7XG4gIHJldHVybiB1cmwuc3Vic3RyaW5nKFxuICAgIHF1ZXJ5U3RhcnQsXG4gICAgZnJhZ21lbnRTdGFydCA+IDAgPyBmcmFnbWVudFN0YXJ0IDogdW5kZWZpbmVkXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IFNIQS0xIGNyeXB0b2dyYXBoaWMgaGFzaC5cbiAqIFZhcmlhYmxlIG5hbWVzIGZvbGxvdyB0aGUgbm90YXRpb24gaW4gRklQUyBQVUIgMTgwLTM6XG4gKiBodHRwOi8vY3NyYy5uaXN0Lmdvdi9wdWJsaWNhdGlvbnMvZmlwcy9maXBzMTgwLTMvZmlwczE4MC0zX2ZpbmFsLnBkZi5cbiAqXG4gKiBVc2FnZTpcbiAqICAgdmFyIHNoYTEgPSBuZXcgc2hhMSgpO1xuICogICBzaGExLnVwZGF0ZShieXRlcyk7XG4gKiAgIHZhciBoYXNoID0gc2hhMS5kaWdlc3QoKTtcbiAqXG4gKiBQZXJmb3JtYW5jZTpcbiAqICAgQ2hyb21lIDIzOiAgIH40MDAgTWJpdC9zXG4gKiAgIEZpcmVmb3ggMTY6ICB+MjUwIE1iaXQvc1xuICpcbiAqL1xuXG4vKipcbiAqIFNIQS0xIGNyeXB0b2dyYXBoaWMgaGFzaCBjb25zdHJ1Y3Rvci5cbiAqXG4gKiBUaGUgcHJvcGVydGllcyBkZWNsYXJlZCBoZXJlIGFyZSBkaXNjdXNzZWQgaW4gdGhlIGFib3ZlIGFsZ29yaXRobSBkb2N1bWVudC5cbiAqIEBjb25zdHJ1Y3RvclxuICogQGZpbmFsXG4gKiBAc3RydWN0XG4gKi9cbmV4cG9ydCBjbGFzcyBTaGExIHtcbiAgLyoqXG4gICAqIEhvbGRzIHRoZSBwcmV2aW91cyB2YWx1ZXMgb2YgYWNjdW11bGF0ZWQgdmFyaWFibGVzIGEtZSBpbiB0aGUgY29tcHJlc3NfXG4gICAqIGZ1bmN0aW9uLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBjaGFpbl86IG51bWJlcltdID0gW107XG5cbiAgLyoqXG4gICAqIEEgYnVmZmVyIGhvbGRpbmcgdGhlIHBhcnRpYWxseSBjb21wdXRlZCBoYXNoIHJlc3VsdC5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYnVmXzogbnVtYmVyW10gPSBbXTtcblxuICAvKipcbiAgICogQW4gYXJyYXkgb2YgODAgYnl0ZXMsIGVhY2ggYSBwYXJ0IG9mIHRoZSBtZXNzYWdlIHRvIGJlIGhhc2hlZC4gIFJlZmVycmVkIHRvXG4gICAqIGFzIHRoZSBtZXNzYWdlIHNjaGVkdWxlIGluIHRoZSBkb2NzLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBXXzogbnVtYmVyW10gPSBbXTtcblxuICAvKipcbiAgICogQ29udGFpbnMgZGF0YSBuZWVkZWQgdG8gcGFkIG1lc3NhZ2VzIGxlc3MgdGhhbiA2NCBieXRlcy5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgcGFkXzogbnVtYmVyW10gPSBbXTtcblxuICAvKipcbiAgICogQHByaXZhdGUge251bWJlcn1cbiAgICovXG4gIHByaXZhdGUgaW5idWZfOiBudW1iZXIgPSAwO1xuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZSB7bnVtYmVyfVxuICAgKi9cbiAgcHJpdmF0ZSB0b3RhbF86IG51bWJlciA9IDA7XG5cbiAgYmxvY2tTaXplOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5ibG9ja1NpemUgPSA1MTIgLyA4O1xuXG4gICAgdGhpcy5wYWRfWzBdID0gMTI4O1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgdGhpcy5ibG9ja1NpemU7ICsraSkge1xuICAgICAgdGhpcy5wYWRfW2ldID0gMDtcbiAgICB9XG5cbiAgICB0aGlzLnJlc2V0KCk7XG4gIH1cblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLmNoYWluX1swXSA9IDB4Njc0NTIzMDE7XG4gICAgdGhpcy5jaGFpbl9bMV0gPSAweGVmY2RhYjg5O1xuICAgIHRoaXMuY2hhaW5fWzJdID0gMHg5OGJhZGNmZTtcbiAgICB0aGlzLmNoYWluX1szXSA9IDB4MTAzMjU0NzY7XG4gICAgdGhpcy5jaGFpbl9bNF0gPSAweGMzZDJlMWYwO1xuXG4gICAgdGhpcy5pbmJ1Zl8gPSAwO1xuICAgIHRoaXMudG90YWxfID0gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnRlcm5hbCBjb21wcmVzcyBoZWxwZXIgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSBidWYgQmxvY2sgdG8gY29tcHJlc3MuXG4gICAqIEBwYXJhbSBvZmZzZXQgT2Zmc2V0IG9mIHRoZSBibG9jayBpbiB0aGUgYnVmZmVyLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY29tcHJlc3NfKGJ1ZjogbnVtYmVyW10gfCBVaW50OEFycmF5IHwgc3RyaW5nLCBvZmZzZXQ/OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIW9mZnNldCkge1xuICAgICAgb2Zmc2V0ID0gMDtcbiAgICB9XG5cbiAgICBjb25zdCBXID0gdGhpcy5XXztcblxuICAgIC8vIGdldCAxNiBiaWcgZW5kaWFuIHdvcmRzXG4gICAgaWYgKHR5cGVvZiBidWYgPT09ICdzdHJpbmcnKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgICAgLy8gVE9ETyh1c2VyKTogW2J1ZyA4MTQwMTIyXSBSZWNlbnQgdmVyc2lvbnMgb2YgU2FmYXJpIGZvciBNYWMgT1MgYW5kIGlPU1xuICAgICAgICAvLyBoYXZlIGEgYnVnIHRoYXQgdHVybnMgdGhlIHBvc3QtaW5jcmVtZW50ICsrIG9wZXJhdG9yIGludG8gcHJlLWluY3JlbWVudFxuICAgICAgICAvLyBkdXJpbmcgSklUIGNvbXBpbGF0aW9uLiAgV2UgaGF2ZSBjb2RlIHRoYXQgZGVwZW5kcyBoZWF2aWx5IG9uIFNIQS0xIGZvclxuICAgICAgICAvLyBjb3JyZWN0bmVzcyBhbmQgd2hpY2ggaXMgYWZmZWN0ZWQgYnkgdGhpcyBidWcsIHNvIEkndmUgcmVtb3ZlZCBhbGwgdXNlc1xuICAgICAgICAvLyBvZiBwb3N0LWluY3JlbWVudCArKyBpbiB3aGljaCB0aGUgcmVzdWx0IHZhbHVlIGlzIHVzZWQuICBXZSBjYW4gcmV2ZXJ0XG4gICAgICAgIC8vIHRoaXMgY2hhbmdlIG9uY2UgdGhlIFNhZmFyaSBidWdcbiAgICAgICAgLy8gKGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMDkwMzYpIGhhcyBiZWVuIGZpeGVkIGFuZFxuICAgICAgICAvLyBtb3N0IGNsaWVudHMgaGF2ZSBiZWVuIHVwZGF0ZWQuXG4gICAgICAgIFdbaV0gPVxuICAgICAgICAgIChidWYuY2hhckNvZGVBdChvZmZzZXQpIDw8IDI0KSB8XG4gICAgICAgICAgKGJ1Zi5jaGFyQ29kZUF0KG9mZnNldCArIDEpIDw8IDE2KSB8XG4gICAgICAgICAgKGJ1Zi5jaGFyQ29kZUF0KG9mZnNldCArIDIpIDw8IDgpIHxcbiAgICAgICAgICBidWYuY2hhckNvZGVBdChvZmZzZXQgKyAzKTtcbiAgICAgICAgb2Zmc2V0ICs9IDQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgICBXW2ldID1cbiAgICAgICAgICAoYnVmW29mZnNldF0gPDwgMjQpIHxcbiAgICAgICAgICAoYnVmW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgICAgICAgKGJ1ZltvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgICAgICAgYnVmW29mZnNldCArIDNdO1xuICAgICAgICBvZmZzZXQgKz0gNDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBleHBhbmQgdG8gODAgd29yZHNcbiAgICBmb3IgKGxldCBpID0gMTY7IGkgPCA4MDsgaSsrKSB7XG4gICAgICBjb25zdCB0ID0gV1tpIC0gM10gXiBXW2kgLSA4XSBeIFdbaSAtIDE0XSBeIFdbaSAtIDE2XTtcbiAgICAgIFdbaV0gPSAoKHQgPDwgMSkgfCAodCA+Pj4gMzEpKSAmIDB4ZmZmZmZmZmY7XG4gICAgfVxuXG4gICAgbGV0IGEgPSB0aGlzLmNoYWluX1swXTtcbiAgICBsZXQgYiA9IHRoaXMuY2hhaW5fWzFdO1xuICAgIGxldCBjID0gdGhpcy5jaGFpbl9bMl07XG4gICAgbGV0IGQgPSB0aGlzLmNoYWluX1szXTtcbiAgICBsZXQgZSA9IHRoaXMuY2hhaW5fWzRdO1xuICAgIGxldCBmLCBrO1xuXG4gICAgLy8gVE9ETyh1c2VyKTogVHJ5IHRvIHVucm9sbCB0aGlzIGxvb3AgdG8gc3BlZWQgdXAgdGhlIGNvbXB1dGF0aW9uLlxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgODA7IGkrKykge1xuICAgICAgaWYgKGkgPCA0MCkge1xuICAgICAgICBpZiAoaSA8IDIwKSB7XG4gICAgICAgICAgZiA9IGQgXiAoYiAmIChjIF4gZCkpO1xuICAgICAgICAgIGsgPSAweDVhODI3OTk5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGYgPSBiIF4gYyBeIGQ7XG4gICAgICAgICAgayA9IDB4NmVkOWViYTE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChpIDwgNjApIHtcbiAgICAgICAgICBmID0gKGIgJiBjKSB8IChkICYgKGIgfCBjKSk7XG4gICAgICAgICAgayA9IDB4OGYxYmJjZGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZiA9IGIgXiBjIF4gZDtcbiAgICAgICAgICBrID0gMHhjYTYyYzFkNjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCB0ID0gKCgoYSA8PCA1KSB8IChhID4+PiAyNykpICsgZiArIGUgKyBrICsgV1tpXSkgJiAweGZmZmZmZmZmO1xuICAgICAgZSA9IGQ7XG4gICAgICBkID0gYztcbiAgICAgIGMgPSAoKGIgPDwgMzApIHwgKGIgPj4+IDIpKSAmIDB4ZmZmZmZmZmY7XG4gICAgICBiID0gYTtcbiAgICAgIGEgPSB0O1xuICAgIH1cblxuICAgIHRoaXMuY2hhaW5fWzBdID0gKHRoaXMuY2hhaW5fWzBdICsgYSkgJiAweGZmZmZmZmZmO1xuICAgIHRoaXMuY2hhaW5fWzFdID0gKHRoaXMuY2hhaW5fWzFdICsgYikgJiAweGZmZmZmZmZmO1xuICAgIHRoaXMuY2hhaW5fWzJdID0gKHRoaXMuY2hhaW5fWzJdICsgYykgJiAweGZmZmZmZmZmO1xuICAgIHRoaXMuY2hhaW5fWzNdID0gKHRoaXMuY2hhaW5fWzNdICsgZCkgJiAweGZmZmZmZmZmO1xuICAgIHRoaXMuY2hhaW5fWzRdID0gKHRoaXMuY2hhaW5fWzRdICsgZSkgJiAweGZmZmZmZmZmO1xuICB9XG5cbiAgdXBkYXRlKGJ5dGVzPzogbnVtYmVyW10gfCBVaW50OEFycmF5IHwgc3RyaW5nLCBsZW5ndGg/OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBUT0RPKGpvaG5sZW56KTogdGlnaHRlbiB0aGUgZnVuY3Rpb24gc2lnbmF0dXJlIGFuZCByZW1vdmUgdGhpcyBjaGVja1xuICAgIGlmIChieXRlcyA9PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBsZW5ndGggPSBieXRlcy5sZW5ndGg7XG4gICAgfVxuXG4gICAgY29uc3QgbGVuZ3RoTWludXNCbG9jayA9IGxlbmd0aCAtIHRoaXMuYmxvY2tTaXplO1xuICAgIGxldCBuID0gMDtcbiAgICAvLyBVc2luZyBsb2NhbCBpbnN0ZWFkIG9mIG1lbWJlciB2YXJpYWJsZXMgZ2l2ZXMgfjUlIHNwZWVkdXAgb24gRmlyZWZveCAxNi5cbiAgICBjb25zdCBidWYgPSB0aGlzLmJ1Zl87XG4gICAgbGV0IGluYnVmID0gdGhpcy5pbmJ1Zl87XG5cbiAgICAvLyBUaGUgb3V0ZXIgd2hpbGUgbG9vcCBzaG91bGQgZXhlY3V0ZSBhdCBtb3N0IHR3aWNlLlxuICAgIHdoaWxlIChuIDwgbGVuZ3RoKSB7XG4gICAgICAvLyBXaGVuIHdlIGhhdmUgbm8gZGF0YSBpbiB0aGUgYmxvY2sgdG8gdG9wIHVwLCB3ZSBjYW4gZGlyZWN0bHkgcHJvY2VzcyB0aGVcbiAgICAgIC8vIGlucHV0IGJ1ZmZlciAoYXNzdW1pbmcgaXQgY29udGFpbnMgc3VmZmljaWVudCBkYXRhKS4gVGhpcyBnaXZlcyB+MjUlXG4gICAgICAvLyBzcGVlZHVwIG9uIENocm9tZSAyMyBhbmQgfjE1JSBzcGVlZHVwIG9uIEZpcmVmb3ggMTYsIGJ1dCByZXF1aXJlcyB0aGF0XG4gICAgICAvLyB0aGUgZGF0YSBpcyBwcm92aWRlZCBpbiBsYXJnZSBjaHVua3MgKG9yIGluIG11bHRpcGxlcyBvZiA2NCBieXRlcykuXG4gICAgICBpZiAoaW5idWYgPT09IDApIHtcbiAgICAgICAgd2hpbGUgKG4gPD0gbGVuZ3RoTWludXNCbG9jaykge1xuICAgICAgICAgIHRoaXMuY29tcHJlc3NfKGJ5dGVzLCBuKTtcbiAgICAgICAgICBuICs9IHRoaXMuYmxvY2tTaXplO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgYnl0ZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHdoaWxlIChuIDwgbGVuZ3RoKSB7XG4gICAgICAgICAgYnVmW2luYnVmXSA9IGJ5dGVzLmNoYXJDb2RlQXQobik7XG4gICAgICAgICAgKytpbmJ1ZjtcbiAgICAgICAgICArK247XG4gICAgICAgICAgaWYgKGluYnVmID09PSB0aGlzLmJsb2NrU2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5jb21wcmVzc18oYnVmKTtcbiAgICAgICAgICAgIGluYnVmID0gMDtcbiAgICAgICAgICAgIC8vIEp1bXAgdG8gdGhlIG91dGVyIGxvb3Agc28gd2UgdXNlIHRoZSBmdWxsLWJsb2NrIG9wdGltaXphdGlvbi5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2hpbGUgKG4gPCBsZW5ndGgpIHtcbiAgICAgICAgICBidWZbaW5idWZdID0gYnl0ZXNbbl07XG4gICAgICAgICAgKytpbmJ1ZjtcbiAgICAgICAgICArK247XG4gICAgICAgICAgaWYgKGluYnVmID09PSB0aGlzLmJsb2NrU2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5jb21wcmVzc18oYnVmKTtcbiAgICAgICAgICAgIGluYnVmID0gMDtcbiAgICAgICAgICAgIC8vIEp1bXAgdG8gdGhlIG91dGVyIGxvb3Agc28gd2UgdXNlIHRoZSBmdWxsLWJsb2NrIG9wdGltaXphdGlvbi5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuaW5idWZfID0gaW5idWY7XG4gICAgdGhpcy50b3RhbF8gKz0gbGVuZ3RoO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqL1xuICBkaWdlc3QoKTogbnVtYmVyW10ge1xuICAgIGNvbnN0IGRpZ2VzdDogbnVtYmVyW10gPSBbXTtcbiAgICBsZXQgdG90YWxCaXRzID0gdGhpcy50b3RhbF8gKiA4O1xuXG4gICAgLy8gQWRkIHBhZCAweDgwIDB4MDAqLlxuICAgIGlmICh0aGlzLmluYnVmXyA8IDU2KSB7XG4gICAgICB0aGlzLnVwZGF0ZSh0aGlzLnBhZF8sIDU2IC0gdGhpcy5pbmJ1Zl8pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVwZGF0ZSh0aGlzLnBhZF8sIHRoaXMuYmxvY2tTaXplIC0gKHRoaXMuaW5idWZfIC0gNTYpKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgIyBiaXRzLlxuICAgIGZvciAobGV0IGkgPSB0aGlzLmJsb2NrU2l6ZSAtIDE7IGkgPj0gNTY7IGktLSkge1xuICAgICAgdGhpcy5idWZfW2ldID0gdG90YWxCaXRzICYgMjU1O1xuICAgICAgdG90YWxCaXRzIC89IDI1NjsgLy8gRG9uJ3QgdXNlIGJpdC1zaGlmdGluZyBoZXJlIVxuICAgIH1cblxuICAgIHRoaXMuY29tcHJlc3NfKHRoaXMuYnVmXyk7XG5cbiAgICBsZXQgbiA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgIGZvciAobGV0IGogPSAyNDsgaiA+PSAwOyBqIC09IDgpIHtcbiAgICAgICAgZGlnZXN0W25dID0gKHRoaXMuY2hhaW5fW2ldID4+IGopICYgMjU1O1xuICAgICAgICArK247XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkaWdlc3Q7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuZXhwb3J0IHR5cGUgTmV4dEZuPFQ+ID0gKHZhbHVlOiBUKSA9PiB2b2lkO1xuZXhwb3J0IHR5cGUgRXJyb3JGbiA9IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG5leHBvcnQgdHlwZSBDb21wbGV0ZUZuID0gKCkgPT4gdm9pZDtcblxuZXhwb3J0IGludGVyZmFjZSBPYnNlcnZlcjxUPiB7XG4gIC8vIENhbGxlZCBvbmNlIGZvciBlYWNoIHZhbHVlIGluIGEgc3RyZWFtIG9mIHZhbHVlcy5cbiAgbmV4dDogTmV4dEZuPFQ+O1xuXG4gIC8vIEEgc3RyZWFtIHRlcm1pbmF0ZXMgYnkgYSBzaW5nbGUgY2FsbCB0byBFSVRIRVIgZXJyb3IoKSBvciBjb21wbGV0ZSgpLlxuICBlcnJvcjogRXJyb3JGbjtcblxuICAvLyBObyBldmVudHMgd2lsbCBiZSBzZW50IHRvIG5leHQoKSBvbmNlIGNvbXBsZXRlKCkgaXMgY2FsbGVkLlxuICBjb21wbGV0ZTogQ29tcGxldGVGbjtcbn1cblxuZXhwb3J0IHR5cGUgUGFydGlhbE9ic2VydmVyPFQ+ID0gUGFydGlhbDxPYnNlcnZlcjxUPj47XG5cbi8vIFRPRE86IFN1cHBvcnQgYWxzbyBVbnN1YnNjcmliZS51bnN1YnNjcmliZT9cbmV4cG9ydCB0eXBlIFVuc3Vic2NyaWJlID0gKCkgPT4gdm9pZDtcblxuLyoqXG4gKiBUaGUgU3Vic2NyaWJlIGludGVyZmFjZSBoYXMgdHdvIGZvcm1zIC0gcGFzc2luZyB0aGUgaW5saW5lIGZ1bmN0aW9uXG4gKiBjYWxsYmFja3MsIG9yIGEgb2JqZWN0IGludGVyZmFjZSB3aXRoIGNhbGxiYWNrIHByb3BlcnRpZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3Vic2NyaWJlPFQ+IHtcbiAgKG5leHQ/OiBOZXh0Rm48VD4sIGVycm9yPzogRXJyb3JGbiwgY29tcGxldGU/OiBDb21wbGV0ZUZuKTogVW5zdWJzY3JpYmU7XG4gIChvYnNlcnZlcjogUGFydGlhbE9ic2VydmVyPFQ+KTogVW5zdWJzY3JpYmU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT2JzZXJ2YWJsZTxUPiB7XG4gIC8vIFN1YnNjcmliZSBtZXRob2RcbiAgc3Vic2NyaWJlOiBTdWJzY3JpYmU8VD47XG59XG5cbmV4cG9ydCB0eXBlIEV4ZWN1dG9yPFQ+ID0gKG9ic2VydmVyOiBPYnNlcnZlcjxUPikgPT4gdm9pZDtcblxuLyoqXG4gKiBIZWxwZXIgdG8gbWFrZSBhIFN1YnNjcmliZSBmdW5jdGlvbiAoanVzdCBsaWtlIFByb21pc2UgaGVscHMgbWFrZSBhXG4gKiBUaGVuYWJsZSkuXG4gKlxuICogQHBhcmFtIGV4ZWN1dG9yIEZ1bmN0aW9uIHdoaWNoIGNhbiBtYWtlIGNhbGxzIHRvIGEgc2luZ2xlIE9ic2VydmVyXG4gKiAgICAgYXMgYSBwcm94eS5cbiAqIEBwYXJhbSBvbk5vT2JzZXJ2ZXJzIENhbGxiYWNrIHdoZW4gY291bnQgb2YgT2JzZXJ2ZXJzIGdvZXMgdG8gemVyby5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVN1YnNjcmliZTxUPihcbiAgZXhlY3V0b3I6IEV4ZWN1dG9yPFQ+LFxuICBvbk5vT2JzZXJ2ZXJzPzogRXhlY3V0b3I8VD5cbik6IFN1YnNjcmliZTxUPiB7XG4gIGNvbnN0IHByb3h5ID0gbmV3IE9ic2VydmVyUHJveHk8VD4oZXhlY3V0b3IsIG9uTm9PYnNlcnZlcnMpO1xuICByZXR1cm4gcHJveHkuc3Vic2NyaWJlLmJpbmQocHJveHkpO1xufVxuXG4vKipcbiAqIEltcGxlbWVudCBmYW4tb3V0IGZvciBhbnkgbnVtYmVyIG9mIE9ic2VydmVycyBhdHRhY2hlZCB2aWEgYSBzdWJzY3JpYmVcbiAqIGZ1bmN0aW9uLlxuICovXG5jbGFzcyBPYnNlcnZlclByb3h5PFQ+IGltcGxlbWVudHMgT2JzZXJ2ZXI8VD4ge1xuICBwcml2YXRlIG9ic2VydmVyczogQXJyYXk8T2JzZXJ2ZXI8VD4+IHwgdW5kZWZpbmVkID0gW107XG4gIHByaXZhdGUgdW5zdWJzY3JpYmVzOiBVbnN1YnNjcmliZVtdID0gW107XG4gIHByaXZhdGUgb25Ob09ic2VydmVyczogRXhlY3V0b3I8VD4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgb2JzZXJ2ZXJDb3VudCA9IDA7XG4gIC8vIE1pY3JvLXRhc2sgc2NoZWR1bGluZyBieSBjYWxsaW5nIHRhc2sudGhlbigpLlxuICBwcml2YXRlIHRhc2sgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgcHJpdmF0ZSBmaW5hbGl6ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBmaW5hbEVycm9yPzogRXJyb3I7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBleGVjdXRvciBGdW5jdGlvbiB3aGljaCBjYW4gbWFrZSBjYWxscyB0byBhIHNpbmdsZSBPYnNlcnZlclxuICAgKiAgICAgYXMgYSBwcm94eS5cbiAgICogQHBhcmFtIG9uTm9PYnNlcnZlcnMgQ2FsbGJhY2sgd2hlbiBjb3VudCBvZiBPYnNlcnZlcnMgZ29lcyB0byB6ZXJvLlxuICAgKi9cbiAgY29uc3RydWN0b3IoZXhlY3V0b3I6IEV4ZWN1dG9yPFQ+LCBvbk5vT2JzZXJ2ZXJzPzogRXhlY3V0b3I8VD4pIHtcbiAgICB0aGlzLm9uTm9PYnNlcnZlcnMgPSBvbk5vT2JzZXJ2ZXJzO1xuICAgIC8vIENhbGwgdGhlIGV4ZWN1dG9yIGFzeW5jaHJvbm91c2x5IHNvIHN1YnNjcmliZXJzIHRoYXQgYXJlIGNhbGxlZFxuICAgIC8vIHN5bmNocm9ub3VzbHkgYWZ0ZXIgdGhlIGNyZWF0aW9uIG9mIHRoZSBzdWJzY3JpYmUgZnVuY3Rpb25cbiAgICAvLyBjYW4gc3RpbGwgcmVjZWl2ZSB0aGUgdmVyeSBmaXJzdCB2YWx1ZSBnZW5lcmF0ZWQgaW4gdGhlIGV4ZWN1dG9yLlxuICAgIHRoaXMudGFza1xuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBleGVjdXRvcih0aGlzKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZSA9PiB7XG4gICAgICAgIHRoaXMuZXJyb3IoZSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIG5leHQodmFsdWU6IFQpOiB2b2lkIHtcbiAgICB0aGlzLmZvckVhY2hPYnNlcnZlcigob2JzZXJ2ZXI6IE9ic2VydmVyPFQ+KSA9PiB7XG4gICAgICBvYnNlcnZlci5uZXh0KHZhbHVlKTtcbiAgICB9KTtcbiAgfVxuXG4gIGVycm9yKGVycm9yOiBFcnJvcik6IHZvaWQge1xuICAgIHRoaXMuZm9yRWFjaE9ic2VydmVyKChvYnNlcnZlcjogT2JzZXJ2ZXI8VD4pID0+IHtcbiAgICAgIG9ic2VydmVyLmVycm9yKGVycm9yKTtcbiAgICB9KTtcbiAgICB0aGlzLmNsb3NlKGVycm9yKTtcbiAgfVxuXG4gIGNvbXBsZXRlKCk6IHZvaWQge1xuICAgIHRoaXMuZm9yRWFjaE9ic2VydmVyKChvYnNlcnZlcjogT2JzZXJ2ZXI8VD4pID0+IHtcbiAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgfSk7XG4gICAgdGhpcy5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZSBmdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGFkZCBhbiBPYnNlcnZlciB0byB0aGUgZmFuLW91dCBsaXN0LlxuICAgKlxuICAgKiAtIFdlIHJlcXVpcmUgdGhhdCBubyBldmVudCBpcyBzZW50IHRvIGEgc3Vic2NyaWJlciBzeW5jaHJvbm91c2x5IHRvIHRoZWlyXG4gICAqICAgY2FsbCB0byBzdWJzY3JpYmUoKS5cbiAgICovXG4gIHN1YnNjcmliZShcbiAgICBuZXh0T3JPYnNlcnZlcj86IE5leHRGbjxUPiB8IFBhcnRpYWxPYnNlcnZlcjxUPixcbiAgICBlcnJvcj86IEVycm9yRm4sXG4gICAgY29tcGxldGU/OiBDb21wbGV0ZUZuXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICBsZXQgb2JzZXJ2ZXI6IE9ic2VydmVyPFQ+O1xuXG4gICAgaWYgKFxuICAgICAgbmV4dE9yT2JzZXJ2ZXIgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgZXJyb3IgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgY29tcGxldGUgPT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIE9ic2VydmVyLicpO1xuICAgIH1cblxuICAgIC8vIEFzc2VtYmxlIGFuIE9ic2VydmVyIG9iamVjdCB3aGVuIHBhc3NlZCBhcyBjYWxsYmFjayBmdW5jdGlvbnMuXG4gICAgaWYgKFxuICAgICAgaW1wbGVtZW50c0FueU1ldGhvZHMobmV4dE9yT2JzZXJ2ZXIgYXMgeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0sIFtcbiAgICAgICAgJ25leHQnLFxuICAgICAgICAnZXJyb3InLFxuICAgICAgICAnY29tcGxldGUnXG4gICAgICBdKVxuICAgICkge1xuICAgICAgb2JzZXJ2ZXIgPSBuZXh0T3JPYnNlcnZlciBhcyBPYnNlcnZlcjxUPjtcbiAgICB9IGVsc2Uge1xuICAgICAgb2JzZXJ2ZXIgPSB7XG4gICAgICAgIG5leHQ6IG5leHRPck9ic2VydmVyIGFzIE5leHRGbjxUPixcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIGNvbXBsZXRlXG4gICAgICB9IGFzIE9ic2VydmVyPFQ+O1xuICAgIH1cblxuICAgIGlmIChvYnNlcnZlci5uZXh0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG9ic2VydmVyLm5leHQgPSBub29wIGFzIE5leHRGbjxUPjtcbiAgICB9XG4gICAgaWYgKG9ic2VydmVyLmVycm9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG9ic2VydmVyLmVycm9yID0gbm9vcCBhcyBFcnJvckZuO1xuICAgIH1cbiAgICBpZiAob2JzZXJ2ZXIuY29tcGxldGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgb2JzZXJ2ZXIuY29tcGxldGUgPSBub29wIGFzIENvbXBsZXRlRm47XG4gICAgfVxuXG4gICAgY29uc3QgdW5zdWIgPSB0aGlzLnVuc3Vic2NyaWJlT25lLmJpbmQodGhpcywgdGhpcy5vYnNlcnZlcnMhLmxlbmd0aCk7XG5cbiAgICAvLyBBdHRlbXB0IHRvIHN1YnNjcmliZSB0byBhIHRlcm1pbmF0ZWQgT2JzZXJ2YWJsZSAtIHdlXG4gICAgLy8ganVzdCByZXNwb25kIHRvIHRoZSBPYnNlcnZlciB3aXRoIHRoZSBmaW5hbCBlcnJvciBvciBjb21wbGV0ZVxuICAgIC8vIGV2ZW50LlxuICAgIGlmICh0aGlzLmZpbmFsaXplZCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICAgICAgdGhpcy50YXNrLnRoZW4oKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGlmICh0aGlzLmZpbmFsRXJyb3IpIHtcbiAgICAgICAgICAgIG9ic2VydmVyLmVycm9yKHRoaXMuZmluYWxFcnJvcik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gbm90aGluZ1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMub2JzZXJ2ZXJzIS5wdXNoKG9ic2VydmVyIGFzIE9ic2VydmVyPFQ+KTtcblxuICAgIHJldHVybiB1bnN1YjtcbiAgfVxuXG4gIC8vIFVuc3Vic2NyaWJlIGlzIHN5bmNocm9ub3VzIC0gd2UgZ3VhcmFudGVlIHRoYXQgbm8gZXZlbnRzIGFyZSBzZW50IHRvXG4gIC8vIGFueSB1bnN1YnNjcmliZWQgT2JzZXJ2ZXIuXG4gIHByaXZhdGUgdW5zdWJzY3JpYmVPbmUoaTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMub2JzZXJ2ZXJzID09PSB1bmRlZmluZWQgfHwgdGhpcy5vYnNlcnZlcnNbaV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGRlbGV0ZSB0aGlzLm9ic2VydmVyc1tpXTtcblxuICAgIHRoaXMub2JzZXJ2ZXJDb3VudCAtPSAxO1xuICAgIGlmICh0aGlzLm9ic2VydmVyQ291bnQgPT09IDAgJiYgdGhpcy5vbk5vT2JzZXJ2ZXJzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMub25Ob09ic2VydmVycyh0aGlzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZvckVhY2hPYnNlcnZlcihmbjogKG9ic2VydmVyOiBPYnNlcnZlcjxUPikgPT4gdm9pZCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmZpbmFsaXplZCkge1xuICAgICAgLy8gQWxyZWFkeSBjbG9zZWQgYnkgcHJldmlvdXMgZXZlbnQuLi4uanVzdCBlYXQgdGhlIGFkZGl0aW9uYWwgdmFsdWVzLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFNpbmNlIHNlbmRPbmUgY2FsbHMgYXN5bmNocm9ub3VzbHkgLSB0aGVyZSBpcyBubyBjaGFuY2UgdGhhdFxuICAgIC8vIHRoaXMub2JzZXJ2ZXJzIHdpbGwgYmVjb21lIHVuZGVmaW5lZC5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMub2JzZXJ2ZXJzIS5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5zZW5kT25lKGksIGZuKTtcbiAgICB9XG4gIH1cblxuICAvLyBDYWxsIHRoZSBPYnNlcnZlciB2aWEgb25lIG9mIGl0J3MgY2FsbGJhY2sgZnVuY3Rpb24uIFdlIGFyZSBjYXJlZnVsIHRvXG4gIC8vIGNvbmZpcm0gdGhhdCB0aGUgb2JzZXJ2ZSBoYXMgbm90IGJlZW4gdW5zdWJzY3JpYmVkIHNpbmNlIHRoaXMgYXN5bmNocm9ub3VzXG4gIC8vIGZ1bmN0aW9uIGhhZCBiZWVuIHF1ZXVlZC5cbiAgcHJpdmF0ZSBzZW5kT25lKGk6IG51bWJlciwgZm46IChvYnNlcnZlcjogT2JzZXJ2ZXI8VD4pID0+IHZvaWQpOiB2b2lkIHtcbiAgICAvLyBFeGVjdXRlIHRoZSBjYWxsYmFjayBhc3luY2hyb25vdXNseVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZmxvYXRpbmctcHJvbWlzZXNcbiAgICB0aGlzLnRhc2sudGhlbigoKSA9PiB7XG4gICAgICBpZiAodGhpcy5vYnNlcnZlcnMgIT09IHVuZGVmaW5lZCAmJiB0aGlzLm9ic2VydmVyc1tpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZm4odGhpcy5vYnNlcnZlcnNbaV0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gSWdub3JlIGV4Y2VwdGlvbnMgcmFpc2VkIGluIE9ic2VydmVycyBvciBtaXNzaW5nIG1ldGhvZHMgb2YgYW5cbiAgICAgICAgICAvLyBPYnNlcnZlci5cbiAgICAgICAgICAvLyBMb2cgZXJyb3IgdG8gY29uc29sZS4gYi8zMTQwNDgwNlxuICAgICAgICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgY29uc29sZS5lcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2UoZXJyPzogRXJyb3IpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5maW5hbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5maW5hbGl6ZWQgPSB0cnVlO1xuICAgIGlmIChlcnIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5maW5hbEVycm9yID0gZXJyO1xuICAgIH1cbiAgICAvLyBQcm94eSBpcyBubyBsb25nZXIgbmVlZGVkIC0gZ2FyYmFnZSBjb2xsZWN0IHJlZmVyZW5jZXNcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgdGhpcy50YXNrLnRoZW4oKCkgPT4ge1xuICAgICAgdGhpcy5vYnNlcnZlcnMgPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLm9uTm9PYnNlcnZlcnMgPSB1bmRlZmluZWQ7XG4gICAgfSk7XG4gIH1cbn1cblxuLyoqIFR1cm4gc3luY2hyb25vdXMgZnVuY3Rpb24gaW50byBvbmUgY2FsbGVkIGFzeW5jaHJvbm91c2x5LiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHlwZXNcbmV4cG9ydCBmdW5jdGlvbiBhc3luYyhmbjogRnVuY3Rpb24sIG9uRXJyb3I/OiBFcnJvckZuKTogRnVuY3Rpb24ge1xuICByZXR1cm4gKC4uLmFyZ3M6IHVua25vd25bXSkgPT4ge1xuICAgIFByb21pc2UucmVzb2x2ZSh0cnVlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBmbiguLi5hcmdzKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICBpZiAob25FcnJvcikge1xuICAgICAgICAgIG9uRXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gdHJ1ZSBpZiB0aGUgb2JqZWN0IHBhc3NlZCBpbiBpbXBsZW1lbnRzIGFueSBvZiB0aGUgbmFtZWQgbWV0aG9kcy5cbiAqL1xuZnVuY3Rpb24gaW1wbGVtZW50c0FueU1ldGhvZHMoXG4gIG9iajogeyBba2V5OiBzdHJpbmddOiB1bmtub3duIH0sXG4gIG1ldGhvZHM6IHN0cmluZ1tdXG4pOiBib29sZWFuIHtcbiAgaWYgKHR5cGVvZiBvYmogIT09ICdvYmplY3QnIHx8IG9iaiA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZvciAoY29uc3QgbWV0aG9kIG9mIG1ldGhvZHMpIHtcbiAgICBpZiAobWV0aG9kIGluIG9iaiAmJiB0eXBlb2Ygb2JqW21ldGhvZF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gbm9vcCgpOiB2b2lkIHtcbiAgLy8gZG8gbm90aGluZ1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQ2hlY2sgdG8gbWFrZSBzdXJlIHRoZSBhcHByb3ByaWF0ZSBudW1iZXIgb2YgYXJndW1lbnRzIGFyZSBwcm92aWRlZCBmb3IgYSBwdWJsaWMgZnVuY3Rpb24uXG4gKiBUaHJvd3MgYW4gZXJyb3IgaWYgaXQgZmFpbHMuXG4gKlxuICogQHBhcmFtIGZuTmFtZSBUaGUgZnVuY3Rpb24gbmFtZVxuICogQHBhcmFtIG1pbkNvdW50IFRoZSBtaW5pbXVtIG51bWJlciBvZiBhcmd1bWVudHMgdG8gYWxsb3cgZm9yIHRoZSBmdW5jdGlvbiBjYWxsXG4gKiBAcGFyYW0gbWF4Q291bnQgVGhlIG1heGltdW0gbnVtYmVyIG9mIGFyZ3VtZW50IHRvIGFsbG93IGZvciB0aGUgZnVuY3Rpb24gY2FsbFxuICogQHBhcmFtIGFyZ0NvdW50IFRoZSBhY3R1YWwgbnVtYmVyIG9mIGFyZ3VtZW50cyBwcm92aWRlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IHZhbGlkYXRlQXJnQ291bnQgPSBmdW5jdGlvbiAoXG4gIGZuTmFtZTogc3RyaW5nLFxuICBtaW5Db3VudDogbnVtYmVyLFxuICBtYXhDb3VudDogbnVtYmVyLFxuICBhcmdDb3VudDogbnVtYmVyXG4pOiB2b2lkIHtcbiAgbGV0IGFyZ0Vycm9yO1xuICBpZiAoYXJnQ291bnQgPCBtaW5Db3VudCkge1xuICAgIGFyZ0Vycm9yID0gJ2F0IGxlYXN0ICcgKyBtaW5Db3VudDtcbiAgfSBlbHNlIGlmIChhcmdDb3VudCA+IG1heENvdW50KSB7XG4gICAgYXJnRXJyb3IgPSBtYXhDb3VudCA9PT0gMCA/ICdub25lJyA6ICdubyBtb3JlIHRoYW4gJyArIG1heENvdW50O1xuICB9XG4gIGlmIChhcmdFcnJvcikge1xuICAgIGNvbnN0IGVycm9yID1cbiAgICAgIGZuTmFtZSArXG4gICAgICAnIGZhaWxlZDogV2FzIGNhbGxlZCB3aXRoICcgK1xuICAgICAgYXJnQ291bnQgK1xuICAgICAgKGFyZ0NvdW50ID09PSAxID8gJyBhcmd1bWVudC4nIDogJyBhcmd1bWVudHMuJykgK1xuICAgICAgJyBFeHBlY3RzICcgK1xuICAgICAgYXJnRXJyb3IgK1xuICAgICAgJy4nO1xuICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG4gIH1cbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgc3RyaW5nIHRvIHByZWZpeCBhbiBlcnJvciBtZXNzYWdlIGFib3V0IGZhaWxlZCBhcmd1bWVudCB2YWxpZGF0aW9uXG4gKlxuICogQHBhcmFtIGZuTmFtZSBUaGUgZnVuY3Rpb24gbmFtZVxuICogQHBhcmFtIGFyZ05hbWUgVGhlIG5hbWUgb2YgdGhlIGFyZ3VtZW50XG4gKiBAcmV0dXJuIFRoZSBwcmVmaXggdG8gYWRkIHRvIHRoZSBlcnJvciB0aHJvd24gZm9yIHZhbGlkYXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlcnJvclByZWZpeChmbk5hbWU6IHN0cmluZywgYXJnTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2ZuTmFtZX0gZmFpbGVkOiAke2FyZ05hbWV9IGFyZ3VtZW50IGA7XG59XG5cbi8qKlxuICogQHBhcmFtIGZuTmFtZVxuICogQHBhcmFtIGFyZ3VtZW50TnVtYmVyXG4gKiBAcGFyYW0gbmFtZXNwYWNlXG4gKiBAcGFyYW0gb3B0aW9uYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlTmFtZXNwYWNlKFxuICBmbk5hbWU6IHN0cmluZyxcbiAgbmFtZXNwYWNlOiBzdHJpbmcsXG4gIG9wdGlvbmFsOiBib29sZWFuXG4pOiB2b2lkIHtcbiAgaWYgKG9wdGlvbmFsICYmICFuYW1lc3BhY2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHR5cGVvZiBuYW1lc3BhY2UgIT09ICdzdHJpbmcnKSB7XG4gICAgLy9UT0RPOiBJIHNob3VsZCBkbyBtb3JlIHZhbGlkYXRpb24gaGVyZS4gV2Ugb25seSBhbGxvdyBjZXJ0YWluIGNoYXJzIGluIG5hbWVzcGFjZXMuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgZXJyb3JQcmVmaXgoZm5OYW1lLCAnbmFtZXNwYWNlJykgKyAnbXVzdCBiZSBhIHZhbGlkIGZpcmViYXNlIG5hbWVzcGFjZS4nXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDYWxsYmFjayhcbiAgZm5OYW1lOiBzdHJpbmcsXG4gIGFyZ3VtZW50TmFtZTogc3RyaW5nLFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xuICBjYWxsYmFjazogRnVuY3Rpb24sXG4gIG9wdGlvbmFsOiBib29sZWFuXG4pOiB2b2lkIHtcbiAgaWYgKG9wdGlvbmFsICYmICFjYWxsYmFjaykge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgZXJyb3JQcmVmaXgoZm5OYW1lLCBhcmd1bWVudE5hbWUpICsgJ211c3QgYmUgYSB2YWxpZCBmdW5jdGlvbi4nXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDb250ZXh0T2JqZWN0KFxuICBmbk5hbWU6IHN0cmluZyxcbiAgYXJndW1lbnROYW1lOiBzdHJpbmcsXG4gIGNvbnRleHQ6IHVua25vd24sXG4gIG9wdGlvbmFsOiBib29sZWFuXG4pOiB2b2lkIHtcbiAgaWYgKG9wdGlvbmFsICYmICFjb250ZXh0KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0eXBlb2YgY29udGV4dCAhPT0gJ29iamVjdCcgfHwgY29udGV4dCA9PT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGVycm9yUHJlZml4KGZuTmFtZSwgYXJndW1lbnROYW1lKSArICdtdXN0IGJlIGEgdmFsaWQgY29udGV4dCBvYmplY3QuJ1xuICAgICk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxNyBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBhc3NlcnQgfSBmcm9tICcuL2Fzc2VydCc7XG5cbi8vIENvZGUgb3JpZ2luYWxseSBjYW1lIGZyb20gZ29vZy5jcnlwdC5zdHJpbmdUb1V0ZjhCeXRlQXJyYXksIGJ1dCBmb3Igc29tZSByZWFzb24gdGhleVxuLy8gYXV0b21hdGljYWxseSByZXBsYWNlZCAnXFxyXFxuJyB3aXRoICdcXG4nLCBhbmQgdGhleSBkaWRuJ3QgaGFuZGxlIHN1cnJvZ2F0ZSBwYWlycyxcbi8vIHNvIGl0J3MgYmVlbiBtb2RpZmllZC5cblxuLy8gTm90ZSB0aGF0IG5vdCBhbGwgVW5pY29kZSBjaGFyYWN0ZXJzIGFwcGVhciBhcyBzaW5nbGUgY2hhcmFjdGVycyBpbiBKYXZhU2NyaXB0IHN0cmluZ3MuXG4vLyBmcm9tQ2hhckNvZGUgcmV0dXJucyB0aGUgVVRGLTE2IGVuY29kaW5nIG9mIGEgY2hhcmFjdGVyIC0gc28gc29tZSBVbmljb2RlIGNoYXJhY3RlcnNcbi8vIHVzZSAyIGNoYXJhY3RlcnMgaW4gSmF2YVNjcmlwdC4gIEFsbCA0LWJ5dGUgVVRGLTggY2hhcmFjdGVycyBiZWdpbiB3aXRoIGEgZmlyc3Rcbi8vIGNoYXJhY3RlciBpbiB0aGUgcmFuZ2UgMHhEODAwIC0gMHhEQkZGICh0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGEgc28tY2FsbGVkIHN1cnJvZ2F0ZVxuLy8gcGFpcikuXG4vLyBTZWUgaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzUuMS8jc2VjLTE1LjEuM1xuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge0FycmF5fVxuICovXG5leHBvcnQgY29uc3Qgc3RyaW5nVG9CeXRlQXJyYXkgPSBmdW5jdGlvbiAoc3RyOiBzdHJpbmcpOiBudW1iZXJbXSB7XG4gIGNvbnN0IG91dDogbnVtYmVyW10gPSBbXTtcbiAgbGV0IHAgPSAwO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjID0gc3RyLmNoYXJDb2RlQXQoaSk7XG5cbiAgICAvLyBJcyB0aGlzIHRoZSBsZWFkIHN1cnJvZ2F0ZSBpbiBhIHN1cnJvZ2F0ZSBwYWlyP1xuICAgIGlmIChjID49IDB4ZDgwMCAmJiBjIDw9IDB4ZGJmZikge1xuICAgICAgY29uc3QgaGlnaCA9IGMgLSAweGQ4MDA7IC8vIHRoZSBoaWdoIDEwIGJpdHMuXG4gICAgICBpKys7XG4gICAgICBhc3NlcnQoaSA8IHN0ci5sZW5ndGgsICdTdXJyb2dhdGUgcGFpciBtaXNzaW5nIHRyYWlsIHN1cnJvZ2F0ZS4nKTtcbiAgICAgIGNvbnN0IGxvdyA9IHN0ci5jaGFyQ29kZUF0KGkpIC0gMHhkYzAwOyAvLyB0aGUgbG93IDEwIGJpdHMuXG4gICAgICBjID0gMHgxMDAwMCArIChoaWdoIDw8IDEwKSArIGxvdztcbiAgICB9XG5cbiAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgb3V0W3ArK10gPSBjO1xuICAgIH0gZWxzZSBpZiAoYyA8IDIwNDgpIHtcbiAgICAgIG91dFtwKytdID0gKGMgPj4gNikgfCAxOTI7XG4gICAgICBvdXRbcCsrXSA9IChjICYgNjMpIHwgMTI4O1xuICAgIH0gZWxzZSBpZiAoYyA8IDY1NTM2KSB7XG4gICAgICBvdXRbcCsrXSA9IChjID4+IDEyKSB8IDIyNDtcbiAgICAgIG91dFtwKytdID0gKChjID4+IDYpICYgNjMpIHwgMTI4O1xuICAgICAgb3V0W3ArK10gPSAoYyAmIDYzKSB8IDEyODtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0W3ArK10gPSAoYyA+PiAxOCkgfCAyNDA7XG4gICAgICBvdXRbcCsrXSA9ICgoYyA+PiAxMikgJiA2MykgfCAxMjg7XG4gICAgICBvdXRbcCsrXSA9ICgoYyA+PiA2KSAmIDYzKSB8IDEyODtcbiAgICAgIG91dFtwKytdID0gKGMgJiA2MykgfCAxMjg7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZSBsZW5ndGggd2l0aG91dCBhY3R1YWxseSBjb252ZXJ0aW5nOyB1c2VmdWwgZm9yIGRvaW5nIGNoZWFwZXIgdmFsaWRhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge251bWJlcn1cbiAqL1xuZXhwb3J0IGNvbnN0IHN0cmluZ0xlbmd0aCA9IGZ1bmN0aW9uIChzdHI6IHN0cmluZyk6IG51bWJlciB7XG4gIGxldCBwID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgIHArKztcbiAgICB9IGVsc2UgaWYgKGMgPCAyMDQ4KSB7XG4gICAgICBwICs9IDI7XG4gICAgfSBlbHNlIGlmIChjID49IDB4ZDgwMCAmJiBjIDw9IDB4ZGJmZikge1xuICAgICAgLy8gTGVhZCBzdXJyb2dhdGUgb2YgYSBzdXJyb2dhdGUgcGFpci4gIFRoZSBwYWlyIHRvZ2V0aGVyIHdpbGwgdGFrZSA0IGJ5dGVzIHRvIHJlcHJlc2VudC5cbiAgICAgIHAgKz0gNDtcbiAgICAgIGkrKzsgLy8gc2tpcCB0cmFpbCBzdXJyb2dhdGUuXG4gICAgfSBlbHNlIHtcbiAgICAgIHAgKz0gMztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHA7XG59O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogVGhlIGFtb3VudCBvZiBtaWxsaXNlY29uZHMgdG8gZXhwb25lbnRpYWxseSBpbmNyZWFzZS5cbiAqL1xuY29uc3QgREVGQVVMVF9JTlRFUlZBTF9NSUxMSVMgPSAxMDAwO1xuXG4vKipcbiAqIFRoZSBmYWN0b3IgdG8gYmFja29mZiBieS5cbiAqIFNob3VsZCBiZSBhIG51bWJlciBncmVhdGVyIHRoYW4gMS5cbiAqL1xuY29uc3QgREVGQVVMVF9CQUNLT0ZGX0ZBQ1RPUiA9IDI7XG5cbi8qKlxuICogVGhlIG1heGltdW0gbWlsbGlzZWNvbmRzIHRvIGluY3JlYXNlIHRvLlxuICpcbiAqIDxwPlZpc2libGUgZm9yIHRlc3RpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9WQUxVRV9NSUxMSVMgPSA0ICogNjAgKiA2MCAqIDEwMDA7IC8vIEZvdXIgaG91cnMsIGxpa2UgaU9TIGFuZCBBbmRyb2lkLlxuXG4vKipcbiAqIFRoZSBwZXJjZW50YWdlIG9mIGJhY2tvZmYgdGltZSB0byByYW5kb21pemUgYnkuXG4gKiBTZWVcbiAqIGh0dHA6Ly9nby9zYWZlLWNsaWVudC1iZWhhdmlvciNzdGVwLTEtZGV0ZXJtaW5lLXRoZS1hcHByb3ByaWF0ZS1yZXRyeS1pbnRlcnZhbC10by1oYW5kbGUtc3Bpa2UtdHJhZmZpY1xuICogZm9yIGNvbnRleHQuXG4gKlxuICogPHA+VmlzaWJsZSBmb3IgdGVzdGluZ1xuICovXG5leHBvcnQgY29uc3QgUkFORE9NX0ZBQ1RPUiA9IDAuNTtcblxuLyoqXG4gKiBCYXNlZCBvbiB0aGUgYmFja29mZiBtZXRob2QgZnJvbVxuICogaHR0cHM6Ly9naXRodWIuY29tL2dvb2dsZS9jbG9zdXJlLWxpYnJhcnkvYmxvYi9tYXN0ZXIvY2xvc3VyZS9nb29nL21hdGgvZXhwb25lbnRpYWxiYWNrb2ZmLmpzLlxuICogRXh0cmFjdGVkIGhlcmUgc28gd2UgZG9uJ3QgbmVlZCB0byBwYXNzIG1ldGFkYXRhIGFuZCBhIHN0YXRlZnVsIEV4cG9uZW50aWFsQmFja29mZiBvYmplY3QgYXJvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlQmFja29mZk1pbGxpcyhcbiAgYmFja29mZkNvdW50OiBudW1iZXIsXG4gIGludGVydmFsTWlsbGlzOiBudW1iZXIgPSBERUZBVUxUX0lOVEVSVkFMX01JTExJUyxcbiAgYmFja29mZkZhY3RvcjogbnVtYmVyID0gREVGQVVMVF9CQUNLT0ZGX0ZBQ1RPUlxuKTogbnVtYmVyIHtcbiAgLy8gQ2FsY3VsYXRlcyBhbiBleHBvbmVudGlhbGx5IGluY3JlYXNpbmcgdmFsdWUuXG4gIC8vIERldmlhdGlvbjogY2FsY3VsYXRlcyB2YWx1ZSBmcm9tIGNvdW50IGFuZCBhIGNvbnN0YW50IGludGVydmFsLCBzbyB3ZSBvbmx5IG5lZWQgdG8gc2F2ZSB2YWx1ZVxuICAvLyBhbmQgY291bnQgdG8gcmVzdG9yZSBzdGF0ZS5cbiAgY29uc3QgY3VyckJhc2VWYWx1ZSA9IGludGVydmFsTWlsbGlzICogTWF0aC5wb3coYmFja29mZkZhY3RvciwgYmFja29mZkNvdW50KTtcblxuICAvLyBBIHJhbmRvbSBcImZ1enpcIiB0byBhdm9pZCB3YXZlcyBvZiByZXRyaWVzLlxuICAvLyBEZXZpYXRpb246IHJhbmRvbUZhY3RvciBpcyByZXF1aXJlZC5cbiAgY29uc3QgcmFuZG9tV2FpdCA9IE1hdGgucm91bmQoXG4gICAgLy8gQSBmcmFjdGlvbiBvZiB0aGUgYmFja29mZiB2YWx1ZSB0byBhZGQvc3VidHJhY3QuXG4gICAgLy8gRGV2aWF0aW9uOiBjaGFuZ2VzIG11bHRpcGxpY2F0aW9uIG9yZGVyIHRvIGltcHJvdmUgcmVhZGFiaWxpdHkuXG4gICAgUkFORE9NX0ZBQ1RPUiAqXG4gICAgICBjdXJyQmFzZVZhbHVlICpcbiAgICAgIC8vIEEgcmFuZG9tIGZsb2F0IChyb3VuZGVkIHRvIGludCBieSBNYXRoLnJvdW5kIGFib3ZlKSBpbiB0aGUgcmFuZ2UgWy0xLCAxXS4gRGV0ZXJtaW5lc1xuICAgICAgLy8gaWYgd2UgYWRkIG9yIHN1YnRyYWN0LlxuICAgICAgKE1hdGgucmFuZG9tKCkgLSAwLjUpICpcbiAgICAgIDJcbiAgKTtcblxuICAvLyBMaW1pdHMgYmFja29mZiB0byBtYXggdG8gYXZvaWQgZWZmZWN0aXZlbHkgcGVybWFuZW50IGJhY2tvZmYuXG4gIHJldHVybiBNYXRoLm1pbihNQVhfVkFMVUVfTUlMTElTLCBjdXJyQmFzZVZhbHVlICsgcmFuZG9tV2FpdCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBQcm92aWRlIEVuZ2xpc2ggb3JkaW5hbCBsZXR0ZXJzIGFmdGVyIGEgbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvcmRpbmFsKGk6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmICghTnVtYmVyLmlzRmluaXRlKGkpKSB7XG4gICAgcmV0dXJuIGAke2l9YDtcbiAgfVxuICByZXR1cm4gaSArIGluZGljYXRvcihpKTtcbn1cblxuZnVuY3Rpb24gaW5kaWNhdG9yKGk6IG51bWJlcik6IHN0cmluZyB7XG4gIGkgPSBNYXRoLmFicyhpKTtcbiAgY29uc3QgY2VudCA9IGkgJSAxMDA7XG4gIGlmIChjZW50ID49IDEwICYmIGNlbnQgPD0gMjApIHtcbiAgICByZXR1cm4gJ3RoJztcbiAgfVxuICBjb25zdCBkZWMgPSBpICUgMTA7XG4gIGlmIChkZWMgPT09IDEpIHtcbiAgICByZXR1cm4gJ3N0JztcbiAgfVxuICBpZiAoZGVjID09PSAyKSB7XG4gICAgcmV0dXJuICduZCc7XG4gIH1cbiAgaWYgKGRlYyA9PT0gMykge1xuICAgIHJldHVybiAncmQnO1xuICB9XG4gIHJldHVybiAndGgnO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcGF0PFQ+IHtcbiAgX2RlbGVnYXRlOiBUO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TW9kdWxhckluc3RhbmNlPEV4cFNlcnZpY2U+KFxuICBzZXJ2aWNlOiBDb21wYXQ8RXhwU2VydmljZT4gfCBFeHBTZXJ2aWNlXG4pOiBFeHBTZXJ2aWNlIHtcbiAgaWYgKHNlcnZpY2UgJiYgKHNlcnZpY2UgYXMgQ29tcGF0PEV4cFNlcnZpY2U+KS5fZGVsZWdhdGUpIHtcbiAgICByZXR1cm4gKHNlcnZpY2UgYXMgQ29tcGF0PEV4cFNlcnZpY2U+KS5fZGVsZWdhdGU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHNlcnZpY2UgYXMgRXhwU2VydmljZTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IENPTlNUQU5UUyB9IGZyb20gJy4vc3JjL2NvbnN0YW50cyc7XG5cbi8vIE92ZXJyaWRpbmcgdGhlIGNvbnN0YW50ICh3ZSBzaG91bGQgYmUgdGhlIG9ubHkgb25lcyBkb2luZyB0aGlzKVxuQ09OU1RBTlRTLk5PREVfQ0xJRU5UID0gdHJ1ZTtcblxuZXhwb3J0ICogZnJvbSAnLi9zcmMvYXNzZXJ0JztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2NyeXB0JztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2NvbnN0YW50cyc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9kZWVwQ29weSc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9kZWZhdWx0cyc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9kZWZlcnJlZCc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9lbXVsYXRvcic7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9lbnZpcm9ubWVudCc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9lcnJvcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvanNvbic7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9qd3QnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvb2JqJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL3Byb21pc2UnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvcXVlcnknO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvc2hhMSc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9zdWJzY3JpYmUnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvdmFsaWRhdGlvbic7XG5leHBvcnQgKiBmcm9tICcuL3NyYy91dGY4JztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL2V4cG9uZW50aWFsX2JhY2tvZmYnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvZm9ybWF0dGVycyc7XG5leHBvcnQgKiBmcm9tICcuL3NyYy9jb21wYXQnO1xuZXhwb3J0ICogZnJvbSAnLi9zcmMvZ2xvYmFsJztcbmV4cG9ydCAqIGZyb20gJy4vc3JjL3VybCc7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbmltcG9ydCB7XG4gIEluc3RhbnRpYXRpb25Nb2RlLFxuICBJbnN0YW5jZUZhY3RvcnksXG4gIENvbXBvbmVudFR5cGUsXG4gIERpY3Rpb25hcnksXG4gIE5hbWUsXG4gIG9uSW5zdGFuY2VDcmVhdGVkQ2FsbGJhY2tcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogQ29tcG9uZW50IGZvciBzZXJ2aWNlIG5hbWUgVCwgZS5nLiBgYXV0aGAsIGBhdXRoLWludGVybmFsYFxuICovXG5leHBvcnQgY2xhc3MgQ29tcG9uZW50PFQgZXh0ZW5kcyBOYW1lID0gTmFtZT4ge1xuICBtdWx0aXBsZUluc3RhbmNlcyA9IGZhbHNlO1xuICAvKipcbiAgICogUHJvcGVydGllcyB0byBiZSBhZGRlZCB0byB0aGUgc2VydmljZSBuYW1lc3BhY2VcbiAgICovXG4gIHNlcnZpY2VQcm9wczogRGljdGlvbmFyeSA9IHt9O1xuXG4gIGluc3RhbnRpYXRpb25Nb2RlID0gSW5zdGFudGlhdGlvbk1vZGUuTEFaWTtcblxuICBvbkluc3RhbmNlQ3JlYXRlZDogb25JbnN0YW5jZUNyZWF0ZWRDYWxsYmFjazxUPiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgcHVibGljIHNlcnZpY2UgbmFtZSwgZS5nLiBhcHAsIGF1dGgsIGZpcmVzdG9yZSwgZGF0YWJhc2VcbiAgICogQHBhcmFtIGluc3RhbmNlRmFjdG9yeSBTZXJ2aWNlIGZhY3RvcnkgcmVzcG9uc2libGUgZm9yIGNyZWF0aW5nIHRoZSBwdWJsaWMgaW50ZXJmYWNlXG4gICAqIEBwYXJhbSB0eXBlIHdoZXRoZXIgdGhlIHNlcnZpY2UgcHJvdmlkZWQgYnkgdGhlIGNvbXBvbmVudCBpcyBwdWJsaWMgb3IgcHJpdmF0ZVxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgbmFtZTogVCxcbiAgICByZWFkb25seSBpbnN0YW5jZUZhY3Rvcnk6IEluc3RhbmNlRmFjdG9yeTxUPixcbiAgICByZWFkb25seSB0eXBlOiBDb21wb25lbnRUeXBlXG4gICkge31cblxuICBzZXRJbnN0YW50aWF0aW9uTW9kZShtb2RlOiBJbnN0YW50aWF0aW9uTW9kZSk6IHRoaXMge1xuICAgIHRoaXMuaW5zdGFudGlhdGlvbk1vZGUgPSBtb2RlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TXVsdGlwbGVJbnN0YW5jZXMobXVsdGlwbGVJbnN0YW5jZXM6IGJvb2xlYW4pOiB0aGlzIHtcbiAgICB0aGlzLm11bHRpcGxlSW5zdGFuY2VzID0gbXVsdGlwbGVJbnN0YW5jZXM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBzZXRTZXJ2aWNlUHJvcHMocHJvcHM6IERpY3Rpb25hcnkpOiB0aGlzIHtcbiAgICB0aGlzLnNlcnZpY2VQcm9wcyA9IHByb3BzO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0SW5zdGFuY2VDcmVhdGVkQ2FsbGJhY2soY2FsbGJhY2s6IG9uSW5zdGFuY2VDcmVhdGVkQ2FsbGJhY2s8VD4pOiB0aGlzIHtcbiAgICB0aGlzLm9uSW5zdGFuY2VDcmVhdGVkID0gY2FsbGJhY2s7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9FTlRSWV9OQU1FID0gJ1tERUZBVUxUXSc7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRGVmZXJyZWQgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBDb21wb25lbnRDb250YWluZXIgfSBmcm9tICcuL2NvbXBvbmVudF9jb250YWluZXInO1xuaW1wb3J0IHsgREVGQVVMVF9FTlRSWV9OQU1FIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHtcbiAgSW5pdGlhbGl6ZU9wdGlvbnMsXG4gIEluc3RhbnRpYXRpb25Nb2RlLFxuICBOYW1lLFxuICBOYW1lU2VydmljZU1hcHBpbmcsXG4gIE9uSW5pdENhbGxCYWNrXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnQnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBpbnN0YW5jZSBmb3Igc2VydmljZSBuYW1lIFQsIGUuZy4gJ2F1dGgnLCAnYXV0aC1pbnRlcm5hbCdcbiAqIE5hbWVTZXJ2aWNlTWFwcGluZ1tUXSBpcyBhbiBhbGlhcyBmb3IgdGhlIHR5cGUgb2YgdGhlIGluc3RhbmNlXG4gKi9cbmV4cG9ydCBjbGFzcyBQcm92aWRlcjxUIGV4dGVuZHMgTmFtZT4ge1xuICBwcml2YXRlIGNvbXBvbmVudDogQ29tcG9uZW50PFQ+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW5zdGFuY2VzOiBNYXA8c3RyaW5nLCBOYW1lU2VydmljZU1hcHBpbmdbVF0+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGluc3RhbmNlc0RlZmVycmVkOiBNYXA8XG4gICAgc3RyaW5nLFxuICAgIERlZmVycmVkPE5hbWVTZXJ2aWNlTWFwcGluZ1tUXT5cbiAgPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnN0YW5jZXNPcHRpb25zOiBNYXA8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gPVxuICAgIG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBvbkluaXRDYWxsYmFja3M6IE1hcDxzdHJpbmcsIFNldDxPbkluaXRDYWxsQmFjazxUPj4+ID0gbmV3IE1hcCgpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbmFtZTogVCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbnRhaW5lcjogQ29tcG9uZW50Q29udGFpbmVyXG4gICkge31cblxuICAvKipcbiAgICogQHBhcmFtIGlkZW50aWZpZXIgQSBwcm92aWRlciBjYW4gcHJvdmlkZSBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgYSBzZXJ2aWNlXG4gICAqIGlmIHRoaXMuY29tcG9uZW50Lm11bHRpcGxlSW5zdGFuY2VzIGlzIHRydWUuXG4gICAqL1xuICBnZXQoaWRlbnRpZmllcj86IHN0cmluZyk6IFByb21pc2U8TmFtZVNlcnZpY2VNYXBwaW5nW1RdPiB7XG4gICAgLy8gaWYgbXVsdGlwbGVJbnN0YW5jZXMgaXMgbm90IHN1cHBvcnRlZCwgdXNlIHRoZSBkZWZhdWx0IG5hbWVcbiAgICBjb25zdCBub3JtYWxpemVkSWRlbnRpZmllciA9IHRoaXMubm9ybWFsaXplSW5zdGFuY2VJZGVudGlmaWVyKGlkZW50aWZpZXIpO1xuXG4gICAgaWYgKCF0aGlzLmluc3RhbmNlc0RlZmVycmVkLmhhcyhub3JtYWxpemVkSWRlbnRpZmllcikpIHtcbiAgICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkPE5hbWVTZXJ2aWNlTWFwcGluZ1tUXT4oKTtcbiAgICAgIHRoaXMuaW5zdGFuY2VzRGVmZXJyZWQuc2V0KG5vcm1hbGl6ZWRJZGVudGlmaWVyLCBkZWZlcnJlZCk7XG5cbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5pc0luaXRpYWxpemVkKG5vcm1hbGl6ZWRJZGVudGlmaWVyKSB8fFxuICAgICAgICB0aGlzLnNob3VsZEF1dG9Jbml0aWFsaXplKClcbiAgICAgICkge1xuICAgICAgICAvLyBpbml0aWFsaXplIHRoZSBzZXJ2aWNlIGlmIGl0IGNhbiBiZSBhdXRvLWluaXRpYWxpemVkXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgaW5zdGFuY2UgPSB0aGlzLmdldE9ySW5pdGlhbGl6ZVNlcnZpY2Uoe1xuICAgICAgICAgICAgaW5zdGFuY2VJZGVudGlmaWVyOiBub3JtYWxpemVkSWRlbnRpZmllclxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGlmIChpbnN0YW5jZSkge1xuICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShpbnN0YW5jZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gd2hlbiB0aGUgaW5zdGFuY2UgZmFjdG9yeSB0aHJvd3MgYW4gZXhjZXB0aW9uIGR1cmluZyBnZXQoKSwgaXQgc2hvdWxkIG5vdCBjYXVzZVxuICAgICAgICAgIC8vIGEgZmF0YWwgZXJyb3IuIFdlIGp1c3QgcmV0dXJuIHRoZSB1bnJlc29sdmVkIHByb21pc2UgaW4gdGhpcyBjYXNlLlxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuaW5zdGFuY2VzRGVmZXJyZWQuZ2V0KG5vcm1hbGl6ZWRJZGVudGlmaWVyKSEucHJvbWlzZTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucy5pZGVudGlmaWVyIEEgcHJvdmlkZXIgY2FuIHByb3ZpZGUgbXVsdGlwbGUgaW5zdGFuY2VzIG9mIGEgc2VydmljZVxuICAgKiBpZiB0aGlzLmNvbXBvbmVudC5tdWx0aXBsZUluc3RhbmNlcyBpcyB0cnVlLlxuICAgKiBAcGFyYW0gb3B0aW9ucy5vcHRpb25hbCBJZiBvcHRpb25hbCBpcyBmYWxzZSBvciBub3QgcHJvdmlkZWQsIHRoZSBtZXRob2QgdGhyb3dzIGFuIGVycm9yIHdoZW5cbiAgICogdGhlIHNlcnZpY2UgaXMgbm90IGltbWVkaWF0ZWx5IGF2YWlsYWJsZS5cbiAgICogSWYgb3B0aW9uYWwgaXMgdHJ1ZSwgdGhlIG1ldGhvZCByZXR1cm5zIG51bGwgaWYgdGhlIHNlcnZpY2UgaXMgbm90IGltbWVkaWF0ZWx5IGF2YWlsYWJsZS5cbiAgICovXG4gIGdldEltbWVkaWF0ZShvcHRpb25zOiB7XG4gICAgaWRlbnRpZmllcj86IHN0cmluZztcbiAgICBvcHRpb25hbDogdHJ1ZTtcbiAgfSk6IE5hbWVTZXJ2aWNlTWFwcGluZ1tUXSB8IG51bGw7XG4gIGdldEltbWVkaWF0ZShvcHRpb25zPzoge1xuICAgIGlkZW50aWZpZXI/OiBzdHJpbmc7XG4gICAgb3B0aW9uYWw/OiBmYWxzZTtcbiAgfSk6IE5hbWVTZXJ2aWNlTWFwcGluZ1tUXTtcbiAgZ2V0SW1tZWRpYXRlKG9wdGlvbnM/OiB7XG4gICAgaWRlbnRpZmllcj86IHN0cmluZztcbiAgICBvcHRpb25hbD86IGJvb2xlYW47XG4gIH0pOiBOYW1lU2VydmljZU1hcHBpbmdbVF0gfCBudWxsIHtcbiAgICAvLyBpZiBtdWx0aXBsZUluc3RhbmNlcyBpcyBub3Qgc3VwcG9ydGVkLCB1c2UgdGhlIGRlZmF1bHQgbmFtZVxuICAgIGNvbnN0IG5vcm1hbGl6ZWRJZGVudGlmaWVyID0gdGhpcy5ub3JtYWxpemVJbnN0YW5jZUlkZW50aWZpZXIoXG4gICAgICBvcHRpb25zPy5pZGVudGlmaWVyXG4gICAgKTtcbiAgICBjb25zdCBvcHRpb25hbCA9IG9wdGlvbnM/Lm9wdGlvbmFsID8/IGZhbHNlO1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy5pc0luaXRpYWxpemVkKG5vcm1hbGl6ZWRJZGVudGlmaWVyKSB8fFxuICAgICAgdGhpcy5zaG91bGRBdXRvSW5pdGlhbGl6ZSgpXG4gICAgKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRPckluaXRpYWxpemVTZXJ2aWNlKHtcbiAgICAgICAgICBpbnN0YW5jZUlkZW50aWZpZXI6IG5vcm1hbGl6ZWRJZGVudGlmaWVyXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAob3B0aW9uYWwpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEluIGNhc2UgYSBjb21wb25lbnQgaXMgbm90IGluaXRpYWxpemVkIGFuZCBzaG91bGQvY2Fubm90IGJlIGF1dG8taW5pdGlhbGl6ZWQgYXQgdGhlIG1vbWVudCwgcmV0dXJuIG51bGwgaWYgdGhlIG9wdGlvbmFsIGZsYWcgaXMgc2V0LCBvciB0aHJvd1xuICAgICAgaWYgKG9wdGlvbmFsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoYFNlcnZpY2UgJHt0aGlzLm5hbWV9IGlzIG5vdCBhdmFpbGFibGVgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBnZXRDb21wb25lbnQoKTogQ29tcG9uZW50PFQ+IHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuY29tcG9uZW50O1xuICB9XG5cbiAgc2V0Q29tcG9uZW50KGNvbXBvbmVudDogQ29tcG9uZW50PFQ+KTogdm9pZCB7XG4gICAgaWYgKGNvbXBvbmVudC5uYW1lICE9PSB0aGlzLm5hbWUpIHtcbiAgICAgIHRocm93IEVycm9yKFxuICAgICAgICBgTWlzbWF0Y2hpbmcgQ29tcG9uZW50ICR7Y29tcG9uZW50Lm5hbWV9IGZvciBQcm92aWRlciAke3RoaXMubmFtZX0uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb21wb25lbnQpIHtcbiAgICAgIHRocm93IEVycm9yKGBDb21wb25lbnQgZm9yICR7dGhpcy5uYW1lfSBoYXMgYWxyZWFkeSBiZWVuIHByb3ZpZGVkYCk7XG4gICAgfVxuXG4gICAgdGhpcy5jb21wb25lbnQgPSBjb21wb25lbnQ7XG5cbiAgICAvLyByZXR1cm4gZWFybHkgd2l0aG91dCBhdHRlbXB0aW5nIHRvIGluaXRpYWxpemUgdGhlIGNvbXBvbmVudCBpZiB0aGUgY29tcG9uZW50IHJlcXVpcmVzIGV4cGxpY2l0IGluaXRpYWxpemF0aW9uIChjYWxsaW5nIGBQcm92aWRlci5pbml0aWFsaXplKClgKVxuICAgIGlmICghdGhpcy5zaG91bGRBdXRvSW5pdGlhbGl6ZSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlIHNlcnZpY2UgaXMgZWFnZXIsIGluaXRpYWxpemUgdGhlIGRlZmF1bHQgaW5zdGFuY2VcbiAgICBpZiAoaXNDb21wb25lbnRFYWdlcihjb21wb25lbnQpKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLmdldE9ySW5pdGlhbGl6ZVNlcnZpY2UoeyBpbnN0YW5jZUlkZW50aWZpZXI6IERFRkFVTFRfRU5UUllfTkFNRSB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gd2hlbiB0aGUgaW5zdGFuY2UgZmFjdG9yeSBmb3IgYW4gZWFnZXIgQ29tcG9uZW50IHRocm93cyBhbiBleGNlcHRpb24gZHVyaW5nIHRoZSBlYWdlclxuICAgICAgICAvLyBpbml0aWFsaXphdGlvbiwgaXQgc2hvdWxkIG5vdCBjYXVzZSBhIGZhdGFsIGVycm9yLlxuICAgICAgICAvLyBUT0RPOiBJbnZlc3RpZ2F0ZSBpZiB3ZSBuZWVkIHRvIG1ha2UgaXQgY29uZmlndXJhYmxlLCBiZWNhdXNlIHNvbWUgY29tcG9uZW50IG1heSB3YW50IHRvIGNhdXNlXG4gICAgICAgIC8vIGEgZmF0YWwgZXJyb3IgaW4gdGhpcyBjYXNlP1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENyZWF0ZSBzZXJ2aWNlIGluc3RhbmNlcyBmb3IgdGhlIHBlbmRpbmcgcHJvbWlzZXMgYW5kIHJlc29sdmUgdGhlbVxuICAgIC8vIE5PVEU6IGlmIHRoaXMubXVsdGlwbGVJbnN0YW5jZXMgaXMgZmFsc2UsIG9ubHkgdGhlIGRlZmF1bHQgaW5zdGFuY2Ugd2lsbCBiZSBjcmVhdGVkXG4gICAgLy8gYW5kIGFsbCBwcm9taXNlcyB3aXRoIHJlc29sdmUgd2l0aCBpdCByZWdhcmRsZXNzIG9mIHRoZSBpZGVudGlmaWVyLlxuICAgIGZvciAoY29uc3QgW1xuICAgICAgaW5zdGFuY2VJZGVudGlmaWVyLFxuICAgICAgaW5zdGFuY2VEZWZlcnJlZFxuICAgIF0gb2YgdGhpcy5pbnN0YW5jZXNEZWZlcnJlZC5lbnRyaWVzKCkpIHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRJZGVudGlmaWVyID1cbiAgICAgICAgdGhpcy5ub3JtYWxpemVJbnN0YW5jZUlkZW50aWZpZXIoaW5zdGFuY2VJZGVudGlmaWVyKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gYGdldE9ySW5pdGlhbGl6ZVNlcnZpY2UoKWAgc2hvdWxkIGFsd2F5cyByZXR1cm4gYSB2YWxpZCBpbnN0YW5jZSBzaW5jZSBhIGNvbXBvbmVudCBpcyBndWFyYW50ZWVkLiB1c2UgISB0byBtYWtlIHR5cGVzY3JpcHQgaGFwcHkuXG4gICAgICAgIGNvbnN0IGluc3RhbmNlID0gdGhpcy5nZXRPckluaXRpYWxpemVTZXJ2aWNlKHtcbiAgICAgICAgICBpbnN0YW5jZUlkZW50aWZpZXI6IG5vcm1hbGl6ZWRJZGVudGlmaWVyXG4gICAgICAgIH0pITtcbiAgICAgICAgaW5zdGFuY2VEZWZlcnJlZC5yZXNvbHZlKGluc3RhbmNlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gd2hlbiB0aGUgaW5zdGFuY2UgZmFjdG9yeSB0aHJvd3MgYW4gZXhjZXB0aW9uLCBpdCBzaG91bGQgbm90IGNhdXNlXG4gICAgICAgIC8vIGEgZmF0YWwgZXJyb3IuIFdlIGp1c3QgbGVhdmUgdGhlIHByb21pc2UgdW5yZXNvbHZlZC5cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjbGVhckluc3RhbmNlKGlkZW50aWZpZXI6IHN0cmluZyA9IERFRkFVTFRfRU5UUllfTkFNRSk6IHZvaWQge1xuICAgIHRoaXMuaW5zdGFuY2VzRGVmZXJyZWQuZGVsZXRlKGlkZW50aWZpZXIpO1xuICAgIHRoaXMuaW5zdGFuY2VzT3B0aW9ucy5kZWxldGUoaWRlbnRpZmllcik7XG4gICAgdGhpcy5pbnN0YW5jZXMuZGVsZXRlKGlkZW50aWZpZXIpO1xuICB9XG5cbiAgLy8gYXBwLmRlbGV0ZSgpIHdpbGwgY2FsbCB0aGlzIG1ldGhvZCBvbiBldmVyeSBwcm92aWRlciB0byBkZWxldGUgdGhlIHNlcnZpY2VzXG4gIC8vIFRPRE86IHNob3VsZCB3ZSBtYXJrIHRoZSBwcm92aWRlciBhcyBkZWxldGVkP1xuICBhc3luYyBkZWxldGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc2VydmljZXMgPSBBcnJheS5mcm9tKHRoaXMuaW5zdGFuY2VzLnZhbHVlcygpKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIC4uLnNlcnZpY2VzXG4gICAgICAgIC5maWx0ZXIoc2VydmljZSA9PiAnSU5URVJOQUwnIGluIHNlcnZpY2UpIC8vIGxlZ2FjeSBzZXJ2aWNlc1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAubWFwKHNlcnZpY2UgPT4gKHNlcnZpY2UgYXMgYW55KS5JTlRFUk5BTCEuZGVsZXRlKCkpLFxuICAgICAgLi4uc2VydmljZXNcbiAgICAgICAgLmZpbHRlcihzZXJ2aWNlID0+ICdfZGVsZXRlJyBpbiBzZXJ2aWNlKSAvLyBtb2R1bGFyaXplZCBzZXJ2aWNlc1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAubWFwKHNlcnZpY2UgPT4gKHNlcnZpY2UgYXMgYW55KS5fZGVsZXRlKCkpXG4gICAgXSk7XG4gIH1cblxuICBpc0NvbXBvbmVudFNldCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnQgIT0gbnVsbDtcbiAgfVxuXG4gIGlzSW5pdGlhbGl6ZWQoaWRlbnRpZmllcjogc3RyaW5nID0gREVGQVVMVF9FTlRSWV9OQU1FKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaW5zdGFuY2VzLmhhcyhpZGVudGlmaWVyKTtcbiAgfVxuXG4gIGdldE9wdGlvbnMoaWRlbnRpZmllcjogc3RyaW5nID0gREVGQVVMVF9FTlRSWV9OQU1FKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIHJldHVybiB0aGlzLmluc3RhbmNlc09wdGlvbnMuZ2V0KGlkZW50aWZpZXIpIHx8IHt9O1xuICB9XG5cbiAgaW5pdGlhbGl6ZShvcHRzOiBJbml0aWFsaXplT3B0aW9ucyA9IHt9KTogTmFtZVNlcnZpY2VNYXBwaW5nW1RdIHtcbiAgICBjb25zdCB7IG9wdGlvbnMgPSB7fSB9ID0gb3B0cztcbiAgICBjb25zdCBub3JtYWxpemVkSWRlbnRpZmllciA9IHRoaXMubm9ybWFsaXplSW5zdGFuY2VJZGVudGlmaWVyKFxuICAgICAgb3B0cy5pbnN0YW5jZUlkZW50aWZpZXJcbiAgICApO1xuICAgIGlmICh0aGlzLmlzSW5pdGlhbGl6ZWQobm9ybWFsaXplZElkZW50aWZpZXIpKSB7XG4gICAgICB0aHJvdyBFcnJvcihcbiAgICAgICAgYCR7dGhpcy5uYW1lfSgke25vcm1hbGl6ZWRJZGVudGlmaWVyfSkgaGFzIGFscmVhZHkgYmVlbiBpbml0aWFsaXplZGBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzQ29tcG9uZW50U2V0KCkpIHtcbiAgICAgIHRocm93IEVycm9yKGBDb21wb25lbnQgJHt0aGlzLm5hbWV9IGhhcyBub3QgYmVlbiByZWdpc3RlcmVkIHlldGApO1xuICAgIH1cblxuICAgIGNvbnN0IGluc3RhbmNlID0gdGhpcy5nZXRPckluaXRpYWxpemVTZXJ2aWNlKHtcbiAgICAgIGluc3RhbmNlSWRlbnRpZmllcjogbm9ybWFsaXplZElkZW50aWZpZXIsXG4gICAgICBvcHRpb25zXG4gICAgfSkhO1xuXG4gICAgLy8gcmVzb2x2ZSBhbnkgcGVuZGluZyBwcm9taXNlIHdhaXRpbmcgZm9yIHRoZSBzZXJ2aWNlIGluc3RhbmNlXG4gICAgZm9yIChjb25zdCBbXG4gICAgICBpbnN0YW5jZUlkZW50aWZpZXIsXG4gICAgICBpbnN0YW5jZURlZmVycmVkXG4gICAgXSBvZiB0aGlzLmluc3RhbmNlc0RlZmVycmVkLmVudHJpZXMoKSkge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZERlZmVycmVkSWRlbnRpZmllciA9XG4gICAgICAgIHRoaXMubm9ybWFsaXplSW5zdGFuY2VJZGVudGlmaWVyKGluc3RhbmNlSWRlbnRpZmllcik7XG4gICAgICBpZiAobm9ybWFsaXplZElkZW50aWZpZXIgPT09IG5vcm1hbGl6ZWREZWZlcnJlZElkZW50aWZpZXIpIHtcbiAgICAgICAgaW5zdGFuY2VEZWZlcnJlZC5yZXNvbHZlKGluc3RhbmNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaW5zdGFuY2U7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGNhbGxiYWNrIC0gYSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgaW52b2tlZCAgYWZ0ZXIgdGhlIHByb3ZpZGVyIGhhcyBiZWVuIGluaXRpYWxpemVkIGJ5IGNhbGxpbmcgcHJvdmlkZXIuaW5pdGlhbGl6ZSgpLlxuICAgKiBUaGUgZnVuY3Rpb24gaXMgaW52b2tlZCBTWU5DSFJPTk9VU0xZLCBzbyBpdCBzaG91bGQgbm90IGV4ZWN1dGUgYW55IGxvbmdydW5uaW5nIHRhc2tzIGluIG9yZGVyIHRvIG5vdCBibG9jayB0aGUgcHJvZ3JhbS5cbiAgICpcbiAgICogQHBhcmFtIGlkZW50aWZpZXIgQW4gb3B0aW9uYWwgaW5zdGFuY2UgaWRlbnRpZmllclxuICAgKiBAcmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrXG4gICAqL1xuICBvbkluaXQoY2FsbGJhY2s6IE9uSW5pdENhbGxCYWNrPFQ+LCBpZGVudGlmaWVyPzogc3RyaW5nKTogKCkgPT4gdm9pZCB7XG4gICAgY29uc3Qgbm9ybWFsaXplZElkZW50aWZpZXIgPSB0aGlzLm5vcm1hbGl6ZUluc3RhbmNlSWRlbnRpZmllcihpZGVudGlmaWVyKTtcbiAgICBjb25zdCBleGlzdGluZ0NhbGxiYWNrcyA9XG4gICAgICB0aGlzLm9uSW5pdENhbGxiYWNrcy5nZXQobm9ybWFsaXplZElkZW50aWZpZXIpID8/XG4gICAgICBuZXcgU2V0PE9uSW5pdENhbGxCYWNrPFQ+PigpO1xuICAgIGV4aXN0aW5nQ2FsbGJhY2tzLmFkZChjYWxsYmFjayk7XG4gICAgdGhpcy5vbkluaXRDYWxsYmFja3Muc2V0KG5vcm1hbGl6ZWRJZGVudGlmaWVyLCBleGlzdGluZ0NhbGxiYWNrcyk7XG5cbiAgICBjb25zdCBleGlzdGluZ0luc3RhbmNlID0gdGhpcy5pbnN0YW5jZXMuZ2V0KG5vcm1hbGl6ZWRJZGVudGlmaWVyKTtcbiAgICBpZiAoZXhpc3RpbmdJbnN0YW5jZSkge1xuICAgICAgY2FsbGJhY2soZXhpc3RpbmdJbnN0YW5jZSwgbm9ybWFsaXplZElkZW50aWZpZXIpO1xuICAgIH1cblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBleGlzdGluZ0NhbGxiYWNrcy5kZWxldGUoY2FsbGJhY2spO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogSW52b2tlIG9uSW5pdCBjYWxsYmFja3Mgc3luY2hyb25vdXNseVxuICAgKiBAcGFyYW0gaW5zdGFuY2UgdGhlIHNlcnZpY2UgaW5zdGFuY2VgXG4gICAqL1xuICBwcml2YXRlIGludm9rZU9uSW5pdENhbGxiYWNrcyhcbiAgICBpbnN0YW5jZTogTmFtZVNlcnZpY2VNYXBwaW5nW1RdLFxuICAgIGlkZW50aWZpZXI6IHN0cmluZ1xuICApOiB2b2lkIHtcbiAgICBjb25zdCBjYWxsYmFja3MgPSB0aGlzLm9uSW5pdENhbGxiYWNrcy5nZXQoaWRlbnRpZmllcik7XG4gICAgaWYgKCFjYWxsYmFja3MpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBjYWxsYmFjayBvZiBjYWxsYmFja3MpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNhbGxiYWNrKGluc3RhbmNlLCBpZGVudGlmaWVyKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBpZ25vcmUgZXJyb3JzIGluIHRoZSBvbkluaXQgY2FsbGJhY2tcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldE9ySW5pdGlhbGl6ZVNlcnZpY2Uoe1xuICAgIGluc3RhbmNlSWRlbnRpZmllcixcbiAgICBvcHRpb25zID0ge31cbiAgfToge1xuICAgIGluc3RhbmNlSWRlbnRpZmllcjogc3RyaW5nO1xuICAgIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfSk6IE5hbWVTZXJ2aWNlTWFwcGluZ1tUXSB8IG51bGwge1xuICAgIGxldCBpbnN0YW5jZSA9IHRoaXMuaW5zdGFuY2VzLmdldChpbnN0YW5jZUlkZW50aWZpZXIpO1xuICAgIGlmICghaW5zdGFuY2UgJiYgdGhpcy5jb21wb25lbnQpIHtcbiAgICAgIGluc3RhbmNlID0gdGhpcy5jb21wb25lbnQuaW5zdGFuY2VGYWN0b3J5KHRoaXMuY29udGFpbmVyLCB7XG4gICAgICAgIGluc3RhbmNlSWRlbnRpZmllcjogbm9ybWFsaXplSWRlbnRpZmllckZvckZhY3RvcnkoaW5zdGFuY2VJZGVudGlmaWVyKSxcbiAgICAgICAgb3B0aW9uc1xuICAgICAgfSk7XG4gICAgICB0aGlzLmluc3RhbmNlcy5zZXQoaW5zdGFuY2VJZGVudGlmaWVyLCBpbnN0YW5jZSEpO1xuICAgICAgdGhpcy5pbnN0YW5jZXNPcHRpb25zLnNldChpbnN0YW5jZUlkZW50aWZpZXIsIG9wdGlvbnMpO1xuXG4gICAgICAvKipcbiAgICAgICAqIEludm9rZSBvbkluaXQgbGlzdGVuZXJzLlxuICAgICAgICogTm90ZSB0aGlzLmNvbXBvbmVudC5vbkluc3RhbmNlQ3JlYXRlZCBpcyBkaWZmZXJlbnQsIHdoaWNoIGlzIHVzZWQgYnkgdGhlIGNvbXBvbmVudCBjcmVhdG9yLFxuICAgICAgICogd2hpbGUgb25Jbml0IGxpc3RlbmVycyBhcmUgcmVnaXN0ZXJlZCBieSBjb25zdW1lcnMgb2YgdGhlIHByb3ZpZGVyLlxuICAgICAgICovXG4gICAgICB0aGlzLmludm9rZU9uSW5pdENhbGxiYWNrcyhpbnN0YW5jZSEsIGluc3RhbmNlSWRlbnRpZmllcik7XG5cbiAgICAgIC8qKlxuICAgICAgICogT3JkZXIgaXMgaW1wb3J0YW50XG4gICAgICAgKiBvbkluc3RhbmNlQ3JlYXRlZCgpIHNob3VsZCBiZSBjYWxsZWQgYWZ0ZXIgdGhpcy5pbnN0YW5jZXMuc2V0KGluc3RhbmNlSWRlbnRpZmllciwgaW5zdGFuY2UpOyB3aGljaFxuICAgICAgICogbWFrZXMgYGlzSW5pdGlhbGl6ZWQoKWAgcmV0dXJuIHRydWUuXG4gICAgICAgKi9cbiAgICAgIGlmICh0aGlzLmNvbXBvbmVudC5vbkluc3RhbmNlQ3JlYXRlZCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHRoaXMuY29tcG9uZW50Lm9uSW5zdGFuY2VDcmVhdGVkKFxuICAgICAgICAgICAgdGhpcy5jb250YWluZXIsXG4gICAgICAgICAgICBpbnN0YW5jZUlkZW50aWZpZXIsXG4gICAgICAgICAgICBpbnN0YW5jZSFcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBpZ25vcmUgZXJyb3JzIGluIHRoZSBvbkluc3RhbmNlQ3JlYXRlZENhbGxiYWNrXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaW5zdGFuY2UgfHwgbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgbm9ybWFsaXplSW5zdGFuY2VJZGVudGlmaWVyKFxuICAgIGlkZW50aWZpZXI6IHN0cmluZyA9IERFRkFVTFRfRU5UUllfTkFNRVxuICApOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmNvbXBvbmVudCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50Lm11bHRpcGxlSW5zdGFuY2VzID8gaWRlbnRpZmllciA6IERFRkFVTFRfRU5UUllfTkFNRTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGlkZW50aWZpZXI7IC8vIGFzc3VtZSBtdWx0aXBsZSBpbnN0YW5jZXMgYXJlIHN1cHBvcnRlZCBiZWZvcmUgdGhlIGNvbXBvbmVudCBpcyBwcm92aWRlZC5cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNob3VsZEF1dG9Jbml0aWFsaXplKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICAhIXRoaXMuY29tcG9uZW50ICYmXG4gICAgICB0aGlzLmNvbXBvbmVudC5pbnN0YW50aWF0aW9uTW9kZSAhPT0gSW5zdGFudGlhdGlvbk1vZGUuRVhQTElDSVRcbiAgICApO1xuICB9XG59XG5cbi8vIHVuZGVmaW5lZCBzaG91bGQgYmUgcGFzc2VkIHRvIHRoZSBzZXJ2aWNlIGZhY3RvcnkgZm9yIHRoZSBkZWZhdWx0IGluc3RhbmNlXG5mdW5jdGlvbiBub3JtYWxpemVJZGVudGlmaWVyRm9yRmFjdG9yeShpZGVudGlmaWVyOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gaWRlbnRpZmllciA9PT0gREVGQVVMVF9FTlRSWV9OQU1FID8gdW5kZWZpbmVkIDogaWRlbnRpZmllcjtcbn1cblxuZnVuY3Rpb24gaXNDb21wb25lbnRFYWdlcjxUIGV4dGVuZHMgTmFtZT4oY29tcG9uZW50OiBDb21wb25lbnQ8VD4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGNvbXBvbmVudC5pbnN0YW50aWF0aW9uTW9kZSA9PT0gSW5zdGFudGlhdGlvbk1vZGUuRUFHRVI7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tICcuL3Byb3ZpZGVyJztcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50JztcbmltcG9ydCB7IE5hbWUgfSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBDb21wb25lbnRDb250YWluZXIgdGhhdCBwcm92aWRlcyBQcm92aWRlcnMgZm9yIHNlcnZpY2UgbmFtZSBULCBlLmcuIGBhdXRoYCwgYGF1dGgtaW50ZXJuYWxgXG4gKi9cbmV4cG9ydCBjbGFzcyBDb21wb25lbnRDb250YWluZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IHByb3ZpZGVycyA9IG5ldyBNYXA8c3RyaW5nLCBQcm92aWRlcjxOYW1lPj4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZykge31cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGNvbXBvbmVudCBDb21wb25lbnQgYmVpbmcgYWRkZWRcbiAgICogQHBhcmFtIG92ZXJ3cml0ZSBXaGVuIGEgY29tcG9uZW50IHdpdGggdGhlIHNhbWUgbmFtZSBoYXMgYWxyZWFkeSBiZWVuIHJlZ2lzdGVyZWQsXG4gICAqIGlmIG92ZXJ3cml0ZSBpcyB0cnVlOiBvdmVyd3JpdGUgdGhlIGV4aXN0aW5nIGNvbXBvbmVudCB3aXRoIHRoZSBuZXcgY29tcG9uZW50IGFuZCBjcmVhdGUgYSBuZXdcbiAgICogcHJvdmlkZXIgd2l0aCB0aGUgbmV3IGNvbXBvbmVudC4gSXQgY2FuIGJlIHVzZWZ1bCBpbiB0ZXN0cyB3aGVyZSB5b3Ugd2FudCB0byB1c2UgZGlmZmVyZW50IG1vY2tzXG4gICAqIGZvciBkaWZmZXJlbnQgdGVzdHMuXG4gICAqIGlmIG92ZXJ3cml0ZSBpcyBmYWxzZTogdGhyb3cgYW4gZXhjZXB0aW9uXG4gICAqL1xuICBhZGRDb21wb25lbnQ8VCBleHRlbmRzIE5hbWU+KGNvbXBvbmVudDogQ29tcG9uZW50PFQ+KTogdm9pZCB7XG4gICAgY29uc3QgcHJvdmlkZXIgPSB0aGlzLmdldFByb3ZpZGVyKGNvbXBvbmVudC5uYW1lKTtcbiAgICBpZiAocHJvdmlkZXIuaXNDb21wb25lbnRTZXQoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29tcG9uZW50ICR7Y29tcG9uZW50Lm5hbWV9IGhhcyBhbHJlYWR5IGJlZW4gcmVnaXN0ZXJlZCB3aXRoICR7dGhpcy5uYW1lfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJvdmlkZXIuc2V0Q29tcG9uZW50KGNvbXBvbmVudCk7XG4gIH1cblxuICBhZGRPck92ZXJ3cml0ZUNvbXBvbmVudDxUIGV4dGVuZHMgTmFtZT4oY29tcG9uZW50OiBDb21wb25lbnQ8VD4pOiB2b2lkIHtcbiAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0UHJvdmlkZXIoY29tcG9uZW50Lm5hbWUpO1xuICAgIGlmIChwcm92aWRlci5pc0NvbXBvbmVudFNldCgpKSB7XG4gICAgICAvLyBkZWxldGUgdGhlIGV4aXN0aW5nIHByb3ZpZGVyIGZyb20gdGhlIGNvbnRhaW5lciwgc28gd2UgY2FuIHJlZ2lzdGVyIHRoZSBuZXcgY29tcG9uZW50XG4gICAgICB0aGlzLnByb3ZpZGVycy5kZWxldGUoY29tcG9uZW50Lm5hbWUpO1xuICAgIH1cblxuICAgIHRoaXMuYWRkQ29tcG9uZW50KGNvbXBvbmVudCk7XG4gIH1cblxuICAvKipcbiAgICogZ2V0UHJvdmlkZXIgcHJvdmlkZXMgYSB0eXBlIHNhZmUgaW50ZXJmYWNlIHdoZXJlIGl0IGNhbiBvbmx5IGJlIGNhbGxlZCB3aXRoIGEgZmllbGQgbmFtZVxuICAgKiBwcmVzZW50IGluIE5hbWVTZXJ2aWNlTWFwcGluZyBpbnRlcmZhY2UuXG4gICAqXG4gICAqIEZpcmViYXNlIFNES3MgcHJvdmlkaW5nIHNlcnZpY2VzIHNob3VsZCBleHRlbmQgTmFtZVNlcnZpY2VNYXBwaW5nIGludGVyZmFjZSB0byByZWdpc3RlclxuICAgKiB0aGVtc2VsdmVzLlxuICAgKi9cbiAgZ2V0UHJvdmlkZXI8VCBleHRlbmRzIE5hbWU+KG5hbWU6IFQpOiBQcm92aWRlcjxUPiB7XG4gICAgaWYgKHRoaXMucHJvdmlkZXJzLmhhcyhuYW1lKSkge1xuICAgICAgcmV0dXJuIHRoaXMucHJvdmlkZXJzLmdldChuYW1lKSBhcyB1bmtub3duIGFzIFByb3ZpZGVyPFQ+O1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBhIFByb3ZpZGVyIGZvciBhIHNlcnZpY2UgdGhhdCBoYXNuJ3QgcmVnaXN0ZXJlZCB3aXRoIEZpcmViYXNlXG4gICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgUHJvdmlkZXI8VD4obmFtZSwgdGhpcyk7XG4gICAgdGhpcy5wcm92aWRlcnMuc2V0KG5hbWUsIHByb3ZpZGVyIGFzIHVua25vd24gYXMgUHJvdmlkZXI8TmFtZT4pO1xuXG4gICAgcmV0dXJuIHByb3ZpZGVyIGFzIFByb3ZpZGVyPFQ+O1xuICB9XG5cbiAgZ2V0UHJvdmlkZXJzKCk6IEFycmF5PFByb3ZpZGVyPE5hbWU+PiB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5wcm92aWRlcnMudmFsdWVzKCkpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IHR5cGUgTG9nTGV2ZWxTdHJpbmcgPVxuICB8ICdkZWJ1ZydcbiAgfCAndmVyYm9zZSdcbiAgfCAnaW5mbydcbiAgfCAnd2FybidcbiAgfCAnZXJyb3InXG4gIHwgJ3NpbGVudCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9nT3B0aW9ucyB7XG4gIGxldmVsOiBMb2dMZXZlbFN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgTG9nQ2FsbGJhY2sgPSAoY2FsbGJhY2tQYXJhbXM6IExvZ0NhbGxiYWNrUGFyYW1zKSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIExvZ0NhbGxiYWNrUGFyYW1zIHtcbiAgbGV2ZWw6IExvZ0xldmVsU3RyaW5nO1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIGFyZ3M6IHVua25vd25bXTtcbiAgdHlwZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgY29udGFpbmVyIGZvciBhbGwgb2YgdGhlIExvZ2dlciBpbnN0YW5jZXNcbiAqL1xuZXhwb3J0IGNvbnN0IGluc3RhbmNlczogTG9nZ2VyW10gPSBbXTtcblxuLyoqXG4gKiBUaGUgSlMgU0RLIHN1cHBvcnRzIDUgbG9nIGxldmVscyBhbmQgYWxzbyBhbGxvd3MgYSB1c2VyIHRoZSBhYmlsaXR5IHRvXG4gKiBzaWxlbmNlIHRoZSBsb2dzIGFsdG9nZXRoZXIuXG4gKlxuICogVGhlIG9yZGVyIGlzIGEgZm9sbG93czpcbiAqIERFQlVHIDwgVkVSQk9TRSA8IElORk8gPCBXQVJOIDwgRVJST1JcbiAqXG4gKiBBbGwgb2YgdGhlIGxvZyB0eXBlcyBhYm92ZSB0aGUgY3VycmVudCBsb2cgbGV2ZWwgd2lsbCBiZSBjYXB0dXJlZCAoaS5lLiBpZlxuICogeW91IHNldCB0aGUgbG9nIGxldmVsIHRvIGBJTkZPYCwgZXJyb3JzIHdpbGwgc3RpbGwgYmUgbG9nZ2VkLCBidXQgYERFQlVHYCBhbmRcbiAqIGBWRVJCT1NFYCBsb2dzIHdpbGwgbm90KVxuICovXG5leHBvcnQgZW51bSBMb2dMZXZlbCB7XG4gIERFQlVHLFxuICBWRVJCT1NFLFxuICBJTkZPLFxuICBXQVJOLFxuICBFUlJPUixcbiAgU0lMRU5UXG59XG5cbmNvbnN0IGxldmVsU3RyaW5nVG9FbnVtOiB7IFtrZXkgaW4gTG9nTGV2ZWxTdHJpbmddOiBMb2dMZXZlbCB9ID0ge1xuICAnZGVidWcnOiBMb2dMZXZlbC5ERUJVRyxcbiAgJ3ZlcmJvc2UnOiBMb2dMZXZlbC5WRVJCT1NFLFxuICAnaW5mbyc6IExvZ0xldmVsLklORk8sXG4gICd3YXJuJzogTG9nTGV2ZWwuV0FSTixcbiAgJ2Vycm9yJzogTG9nTGV2ZWwuRVJST1IsXG4gICdzaWxlbnQnOiBMb2dMZXZlbC5TSUxFTlRcbn07XG5cbi8qKlxuICogVGhlIGRlZmF1bHQgbG9nIGxldmVsXG4gKi9cbmNvbnN0IGRlZmF1bHRMb2dMZXZlbDogTG9nTGV2ZWwgPSBMb2dMZXZlbC5JTkZPO1xuXG4vKipcbiAqIFdlIGFsbG93IHVzZXJzIHRoZSBhYmlsaXR5IHRvIHBhc3MgdGhlaXIgb3duIGxvZyBoYW5kbGVyLiBXZSB3aWxsIHBhc3MgdGhlXG4gKiB0eXBlIG9mIGxvZywgdGhlIGN1cnJlbnQgbG9nIGxldmVsLCBhbmQgYW55IG90aGVyIGFyZ3VtZW50cyBwYXNzZWQgKGkuZS4gdGhlXG4gKiBtZXNzYWdlcyB0aGF0IHRoZSB1c2VyIHdhbnRzIHRvIGxvZykgdG8gdGhpcyBmdW5jdGlvbi5cbiAqL1xuZXhwb3J0IHR5cGUgTG9nSGFuZGxlciA9IChcbiAgbG9nZ2VySW5zdGFuY2U6IExvZ2dlcixcbiAgbG9nVHlwZTogTG9nTGV2ZWwsXG4gIC4uLmFyZ3M6IHVua25vd25bXVxuKSA9PiB2b2lkO1xuXG4vKipcbiAqIEJ5IGRlZmF1bHQsIGBjb25zb2xlLmRlYnVnYCBpcyBub3QgZGlzcGxheWVkIGluIHRoZSBkZXZlbG9wZXIgY29uc29sZSAoaW5cbiAqIGNocm9tZSkuIFRvIGF2b2lkIGZvcmNpbmcgdXNlcnMgdG8gaGF2ZSB0byBvcHQtaW4gdG8gdGhlc2UgbG9ncyB0d2ljZVxuICogKGkuZS4gb25jZSBmb3IgZmlyZWJhc2UsIGFuZCBvbmNlIGluIHRoZSBjb25zb2xlKSwgd2UgYXJlIHNlbmRpbmcgYERFQlVHYFxuICogbG9ncyB0byB0aGUgYGNvbnNvbGUubG9nYCBmdW5jdGlvbi5cbiAqL1xuY29uc3QgQ29uc29sZU1ldGhvZCA9IHtcbiAgW0xvZ0xldmVsLkRFQlVHXTogJ2xvZycsXG4gIFtMb2dMZXZlbC5WRVJCT1NFXTogJ2xvZycsXG4gIFtMb2dMZXZlbC5JTkZPXTogJ2luZm8nLFxuICBbTG9nTGV2ZWwuV0FSTl06ICd3YXJuJyxcbiAgW0xvZ0xldmVsLkVSUk9SXTogJ2Vycm9yJ1xufTtcblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBsb2cgaGFuZGxlciB3aWxsIGZvcndhcmQgREVCVUcsIFZFUkJPU0UsIElORk8sIFdBUk4sIGFuZCBFUlJPUlxuICogbWVzc2FnZXMgb24gdG8gdGhlaXIgY29ycmVzcG9uZGluZyBjb25zb2xlIGNvdW50ZXJwYXJ0cyAoaWYgdGhlIGxvZyBtZXRob2RcbiAqIGlzIHN1cHBvcnRlZCBieSB0aGUgY3VycmVudCBsb2cgbGV2ZWwpXG4gKi9cbmNvbnN0IGRlZmF1bHRMb2dIYW5kbGVyOiBMb2dIYW5kbGVyID0gKGluc3RhbmNlLCBsb2dUeXBlLCAuLi5hcmdzKTogdm9pZCA9PiB7XG4gIGlmIChsb2dUeXBlIDwgaW5zdGFuY2UubG9nTGV2ZWwpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgbm93ID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICBjb25zdCBtZXRob2QgPSBDb25zb2xlTWV0aG9kW2xvZ1R5cGUgYXMga2V5b2YgdHlwZW9mIENvbnNvbGVNZXRob2RdO1xuICBpZiAobWV0aG9kKSB7XG4gICAgY29uc29sZVttZXRob2QgYXMgJ2xvZycgfCAnaW5mbycgfCAnd2FybicgfCAnZXJyb3InXShcbiAgICAgIGBbJHtub3d9XSAgJHtpbnN0YW5jZS5uYW1lfTpgLFxuICAgICAgLi4uYXJnc1xuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEF0dGVtcHRlZCB0byBsb2cgYSBtZXNzYWdlIHdpdGggYW4gaW52YWxpZCBsb2dUeXBlICh2YWx1ZTogJHtsb2dUeXBlfSlgXG4gICAgKTtcbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIExvZ2dlciB7XG4gIC8qKlxuICAgKiBHaXZlcyB5b3UgYW4gaW5zdGFuY2Ugb2YgYSBMb2dnZXIgdG8gY2FwdHVyZSBtZXNzYWdlcyBhY2NvcmRpbmcgdG9cbiAgICogRmlyZWJhc2UncyBsb2dnaW5nIHNjaGVtZS5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgdGhhdCB0aGUgbG9ncyB3aWxsIGJlIGFzc29jaWF0ZWQgd2l0aFxuICAgKi9cbiAgY29uc3RydWN0b3IocHVibGljIG5hbWU6IHN0cmluZykge1xuICAgIC8qKlxuICAgICAqIENhcHR1cmUgdGhlIGN1cnJlbnQgaW5zdGFuY2UgZm9yIGxhdGVyIHVzZVxuICAgICAqL1xuICAgIGluc3RhbmNlcy5wdXNoKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBsb2cgbGV2ZWwgb2YgdGhlIGdpdmVuIExvZ2dlciBpbnN0YW5jZS5cbiAgICovXG4gIHByaXZhdGUgX2xvZ0xldmVsID0gZGVmYXVsdExvZ0xldmVsO1xuXG4gIGdldCBsb2dMZXZlbCgpOiBMb2dMZXZlbCB7XG4gICAgcmV0dXJuIHRoaXMuX2xvZ0xldmVsO1xuICB9XG5cbiAgc2V0IGxvZ0xldmVsKHZhbDogTG9nTGV2ZWwpIHtcbiAgICBpZiAoISh2YWwgaW4gTG9nTGV2ZWwpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIHZhbHVlIFwiJHt2YWx9XCIgYXNzaWduZWQgdG8gXFxgbG9nTGV2ZWxcXGBgKTtcbiAgICB9XG4gICAgdGhpcy5fbG9nTGV2ZWwgPSB2YWw7XG4gIH1cblxuICAvLyBXb3JrYXJvdW5kIGZvciBzZXR0ZXIvZ2V0dGVyIGhhdmluZyB0byBiZSB0aGUgc2FtZSB0eXBlLlxuICBzZXRMb2dMZXZlbCh2YWw6IExvZ0xldmVsIHwgTG9nTGV2ZWxTdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl9sb2dMZXZlbCA9IHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gbGV2ZWxTdHJpbmdUb0VudW1bdmFsXSA6IHZhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbWFpbiAoaW50ZXJuYWwpIGxvZyBoYW5kbGVyIGZvciB0aGUgTG9nZ2VyIGluc3RhbmNlLlxuICAgKiBDYW4gYmUgc2V0IHRvIGEgbmV3IGZ1bmN0aW9uIGluIGludGVybmFsIHBhY2thZ2UgY29kZSBidXQgbm90IGJ5IHVzZXIuXG4gICAqL1xuICBwcml2YXRlIF9sb2dIYW5kbGVyOiBMb2dIYW5kbGVyID0gZGVmYXVsdExvZ0hhbmRsZXI7XG4gIGdldCBsb2dIYW5kbGVyKCk6IExvZ0hhbmRsZXIge1xuICAgIHJldHVybiB0aGlzLl9sb2dIYW5kbGVyO1xuICB9XG4gIHNldCBsb2dIYW5kbGVyKHZhbDogTG9nSGFuZGxlcikge1xuICAgIGlmICh0eXBlb2YgdmFsICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdWYWx1ZSBhc3NpZ25lZCB0byBgbG9nSGFuZGxlcmAgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgfVxuICAgIHRoaXMuX2xvZ0hhbmRsZXIgPSB2YWw7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG9wdGlvbmFsLCBhZGRpdGlvbmFsLCB1c2VyLWRlZmluZWQgbG9nIGhhbmRsZXIgZm9yIHRoZSBMb2dnZXIgaW5zdGFuY2UuXG4gICAqL1xuICBwcml2YXRlIF91c2VyTG9nSGFuZGxlcjogTG9nSGFuZGxlciB8IG51bGwgPSBudWxsO1xuICBnZXQgdXNlckxvZ0hhbmRsZXIoKTogTG9nSGFuZGxlciB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl91c2VyTG9nSGFuZGxlcjtcbiAgfVxuICBzZXQgdXNlckxvZ0hhbmRsZXIodmFsOiBMb2dIYW5kbGVyIHwgbnVsbCkge1xuICAgIHRoaXMuX3VzZXJMb2dIYW5kbGVyID0gdmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBmdW5jdGlvbnMgYmVsb3cgYXJlIGFsbCBiYXNlZCBvbiB0aGUgYGNvbnNvbGVgIGludGVyZmFjZVxuICAgKi9cblxuICBkZWJ1ZyguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcbiAgICB0aGlzLl91c2VyTG9nSGFuZGxlciAmJiB0aGlzLl91c2VyTG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5ERUJVRywgLi4uYXJncyk7XG4gICAgdGhpcy5fbG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5ERUJVRywgLi4uYXJncyk7XG4gIH1cbiAgbG9nKC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuICAgIHRoaXMuX3VzZXJMb2dIYW5kbGVyICYmXG4gICAgICB0aGlzLl91c2VyTG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5WRVJCT1NFLCAuLi5hcmdzKTtcbiAgICB0aGlzLl9sb2dIYW5kbGVyKHRoaXMsIExvZ0xldmVsLlZFUkJPU0UsIC4uLmFyZ3MpO1xuICB9XG4gIGluZm8oLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgdGhpcy5fdXNlckxvZ0hhbmRsZXIgJiYgdGhpcy5fdXNlckxvZ0hhbmRsZXIodGhpcywgTG9nTGV2ZWwuSU5GTywgLi4uYXJncyk7XG4gICAgdGhpcy5fbG9nSGFuZGxlcih0aGlzLCBMb2dMZXZlbC5JTkZPLCAuLi5hcmdzKTtcbiAgfVxuICB3YXJuKC4uLmFyZ3M6IHVua25vd25bXSk6IHZvaWQge1xuICAgIHRoaXMuX3VzZXJMb2dIYW5kbGVyICYmIHRoaXMuX3VzZXJMb2dIYW5kbGVyKHRoaXMsIExvZ0xldmVsLldBUk4sIC4uLmFyZ3MpO1xuICAgIHRoaXMuX2xvZ0hhbmRsZXIodGhpcywgTG9nTGV2ZWwuV0FSTiwgLi4uYXJncyk7XG4gIH1cbiAgZXJyb3IoLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgdGhpcy5fdXNlckxvZ0hhbmRsZXIgJiYgdGhpcy5fdXNlckxvZ0hhbmRsZXIodGhpcywgTG9nTGV2ZWwuRVJST1IsIC4uLmFyZ3MpO1xuICAgIHRoaXMuX2xvZ0hhbmRsZXIodGhpcywgTG9nTGV2ZWwuRVJST1IsIC4uLmFyZ3MpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRMb2dMZXZlbChsZXZlbDogTG9nTGV2ZWxTdHJpbmcgfCBMb2dMZXZlbCk6IHZvaWQge1xuICBpbnN0YW5jZXMuZm9yRWFjaChpbnN0ID0+IHtcbiAgICBpbnN0LnNldExvZ0xldmVsKGxldmVsKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRVc2VyTG9nSGFuZGxlcihcbiAgbG9nQ2FsbGJhY2s6IExvZ0NhbGxiYWNrIHwgbnVsbCxcbiAgb3B0aW9ucz86IExvZ09wdGlvbnNcbik6IHZvaWQge1xuICBmb3IgKGNvbnN0IGluc3RhbmNlIG9mIGluc3RhbmNlcykge1xuICAgIGxldCBjdXN0b21Mb2dMZXZlbDogTG9nTGV2ZWwgfCBudWxsID0gbnVsbDtcbiAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmxldmVsKSB7XG4gICAgICBjdXN0b21Mb2dMZXZlbCA9IGxldmVsU3RyaW5nVG9FbnVtW29wdGlvbnMubGV2ZWxdO1xuICAgIH1cbiAgICBpZiAobG9nQ2FsbGJhY2sgPT09IG51bGwpIHtcbiAgICAgIGluc3RhbmNlLnVzZXJMb2dIYW5kbGVyID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgaW5zdGFuY2UudXNlckxvZ0hhbmRsZXIgPSAoXG4gICAgICAgIGluc3RhbmNlOiBMb2dnZXIsXG4gICAgICAgIGxldmVsOiBMb2dMZXZlbCxcbiAgICAgICAgLi4uYXJnczogdW5rbm93bltdXG4gICAgICApID0+IHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IGFyZ3NcbiAgICAgICAgICAubWFwKGFyZyA9PiB7XG4gICAgICAgICAgICBpZiAoYXJnID09IG51bGwpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHJldHVybiBhcmc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInIHx8IHR5cGVvZiBhcmcgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFyZyBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICAgIHJldHVybiBhcmcubWVzc2FnZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGFyZyk7XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGlnbm9yZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgICAgLmZpbHRlcihhcmcgPT4gYXJnKVxuICAgICAgICAgIC5qb2luKCcgJyk7XG4gICAgICAgIGlmIChsZXZlbCA+PSAoY3VzdG9tTG9nTGV2ZWwgPz8gaW5zdGFuY2UubG9nTGV2ZWwpKSB7XG4gICAgICAgICAgbG9nQ2FsbGJhY2soe1xuICAgICAgICAgICAgbGV2ZWw6IExvZ0xldmVsW2xldmVsXS50b0xvd2VyQ2FzZSgpIGFzIExvZ0xldmVsU3RyaW5nLFxuICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgICB0eXBlOiBpbnN0YW5jZS5uYW1lXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgQ29tcG9uZW50Q29udGFpbmVyLFxuICBDb21wb25lbnRUeXBlLFxuICBQcm92aWRlcixcbiAgTmFtZVxufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IFBsYXRmb3JtTG9nZ2VyU2VydmljZSwgVmVyc2lvblNlcnZpY2UgfSBmcm9tICcuL3R5cGVzJztcblxuZXhwb3J0IGNsYXNzIFBsYXRmb3JtTG9nZ2VyU2VydmljZUltcGwgaW1wbGVtZW50cyBQbGF0Zm9ybUxvZ2dlclNlcnZpY2Uge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGNvbnRhaW5lcjogQ29tcG9uZW50Q29udGFpbmVyKSB7fVxuICAvLyBJbiBpbml0aWFsIGltcGxlbWVudGF0aW9uLCB0aGlzIHdpbGwgYmUgY2FsbGVkIGJ5IGluc3RhbGxhdGlvbnMgb25cbiAgLy8gYXV0aCB0b2tlbiByZWZyZXNoLCBhbmQgaW5zdGFsbGF0aW9ucyB3aWxsIHNlbmQgdGhpcyBzdHJpbmcuXG4gIGdldFBsYXRmb3JtSW5mb1N0cmluZygpOiBzdHJpbmcge1xuICAgIGNvbnN0IHByb3ZpZGVycyA9IHRoaXMuY29udGFpbmVyLmdldFByb3ZpZGVycygpO1xuICAgIC8vIExvb3AgdGhyb3VnaCBwcm92aWRlcnMgYW5kIGdldCBsaWJyYXJ5L3ZlcnNpb24gcGFpcnMgZnJvbSBhbnkgdGhhdCBhcmVcbiAgICAvLyB2ZXJzaW9uIGNvbXBvbmVudHMuXG4gICAgcmV0dXJuIHByb3ZpZGVyc1xuICAgICAgLm1hcChwcm92aWRlciA9PiB7XG4gICAgICAgIGlmIChpc1ZlcnNpb25TZXJ2aWNlUHJvdmlkZXIocHJvdmlkZXIpKSB7XG4gICAgICAgICAgY29uc3Qgc2VydmljZSA9IHByb3ZpZGVyLmdldEltbWVkaWF0ZSgpIGFzIFZlcnNpb25TZXJ2aWNlO1xuICAgICAgICAgIHJldHVybiBgJHtzZXJ2aWNlLmxpYnJhcnl9LyR7c2VydmljZS52ZXJzaW9ufWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKGxvZ1N0cmluZyA9PiBsb2dTdHJpbmcpXG4gICAgICAuam9pbignICcpO1xuICB9XG59XG4vKipcbiAqXG4gKiBAcGFyYW0gcHJvdmlkZXIgY2hlY2sgaWYgdGhpcyBwcm92aWRlciBwcm92aWRlcyBhIFZlcnNpb25TZXJ2aWNlXG4gKlxuICogTk9URTogVXNpbmcgUHJvdmlkZXI8J2FwcC12ZXJzaW9uJz4gaXMgYSBoYWNrIHRvIGluZGljYXRlIHRoYXQgdGhlIHByb3ZpZGVyXG4gKiBwcm92aWRlcyBWZXJzaW9uU2VydmljZS4gVGhlIHByb3ZpZGVyIGlzIG5vdCBuZWNlc3NhcmlseSBhICdhcHAtdmVyc2lvbidcbiAqIHByb3ZpZGVyLlxuICovXG5mdW5jdGlvbiBpc1ZlcnNpb25TZXJ2aWNlUHJvdmlkZXIocHJvdmlkZXI6IFByb3ZpZGVyPE5hbWU+KTogYm9vbGVhbiB7XG4gIGNvbnN0IGNvbXBvbmVudCA9IHByb3ZpZGVyLmdldENvbXBvbmVudCgpO1xuICByZXR1cm4gY29tcG9uZW50Py50eXBlID09PSBDb21wb25lbnRUeXBlLlZFUlNJT047XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnQGZpcmViYXNlL2xvZ2dlcic7XG5cbmV4cG9ydCBjb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdAZmlyZWJhc2UvYXBwJyk7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgbmFtZSBhcyBhcHBOYW1lIH0gZnJvbSAnLi4vcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYXBwQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uL2FwcC1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYW5hbHl0aWNzQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2FuYWx5dGljcy1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYW5hbHl0aWNzTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2FuYWx5dGljcy9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBhcHBDaGVja0NvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9hcHAtY2hlY2stY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGFwcENoZWNrTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2FwcC1jaGVjay9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBhdXRoTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2F1dGgvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYXV0aENvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9hdXRoLWNvbXBhdC9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBkYXRhYmFzZU5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9kYXRhYmFzZS9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBkYXRhY29ubmVjdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9kYXRhLWNvbm5lY3QvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgZGF0YWJhc2VDb21wYXROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvZGF0YWJhc2UtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGZ1bmN0aW9uc05hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9mdW5jdGlvbnMvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgZnVuY3Rpb25zQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2Z1bmN0aW9ucy1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgaW5zdGFsbGF0aW9uc05hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9pbnN0YWxsYXRpb25zL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGluc3RhbGxhdGlvbnNDb21wYXROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvaW5zdGFsbGF0aW9ucy1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgbWVzc2FnaW5nTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL21lc3NhZ2luZy9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBtZXNzYWdpbmdDb21wYXROYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvbWVzc2FnaW5nLWNvbXBhdC9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBwZXJmb3JtYW5jZU5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9wZXJmb3JtYW5jZS9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBwZXJmb3JtYW5jZUNvbXBhdE5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9wZXJmb3JtYW5jZS1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgcmVtb3RlQ29uZmlnTmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL3JlbW90ZS1jb25maWcvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgcmVtb3RlQ29uZmlnQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL3JlbW90ZS1jb25maWctY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIHN0b3JhZ2VOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvc3RvcmFnZS9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgbmFtZSBhcyBzdG9yYWdlQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL3N0b3JhZ2UtY29tcGF0L3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBuYW1lIGFzIGZpcmVzdG9yZU5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9maXJlc3RvcmUvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgYWlOYW1lIH0gZnJvbSAnLi4vLi4vLi4vcGFja2FnZXMvYWkvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgZmlyZXN0b3JlQ29tcGF0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2VzL2ZpcmVzdG9yZS1jb21wYXQvcGFja2FnZS5qc29uJztcbmltcG9ydCB7IG5hbWUgYXMgcGFja2FnZU5hbWUgfSBmcm9tICcuLi8uLi8uLi9wYWNrYWdlcy9maXJlYmFzZS9wYWNrYWdlLmpzb24nO1xuXG4vKipcbiAqIFRoZSBkZWZhdWx0IGFwcCBuYW1lXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0VOVFJZX05BTUUgPSAnW0RFRkFVTFRdJztcblxuZXhwb3J0IGNvbnN0IFBMQVRGT1JNX0xPR19TVFJJTkcgPSB7XG4gIFthcHBOYW1lXTogJ2ZpcmUtY29yZScsXG4gIFthcHBDb21wYXROYW1lXTogJ2ZpcmUtY29yZS1jb21wYXQnLFxuICBbYW5hbHl0aWNzTmFtZV06ICdmaXJlLWFuYWx5dGljcycsXG4gIFthbmFseXRpY3NDb21wYXROYW1lXTogJ2ZpcmUtYW5hbHl0aWNzLWNvbXBhdCcsXG4gIFthcHBDaGVja05hbWVdOiAnZmlyZS1hcHAtY2hlY2snLFxuICBbYXBwQ2hlY2tDb21wYXROYW1lXTogJ2ZpcmUtYXBwLWNoZWNrLWNvbXBhdCcsXG4gIFthdXRoTmFtZV06ICdmaXJlLWF1dGgnLFxuICBbYXV0aENvbXBhdE5hbWVdOiAnZmlyZS1hdXRoLWNvbXBhdCcsXG4gIFtkYXRhYmFzZU5hbWVdOiAnZmlyZS1ydGRiJyxcbiAgW2RhdGFjb25uZWN0TmFtZV06ICdmaXJlLWRhdGEtY29ubmVjdCcsXG4gIFtkYXRhYmFzZUNvbXBhdE5hbWVdOiAnZmlyZS1ydGRiLWNvbXBhdCcsXG4gIFtmdW5jdGlvbnNOYW1lXTogJ2ZpcmUtZm4nLFxuICBbZnVuY3Rpb25zQ29tcGF0TmFtZV06ICdmaXJlLWZuLWNvbXBhdCcsXG4gIFtpbnN0YWxsYXRpb25zTmFtZV06ICdmaXJlLWlpZCcsXG4gIFtpbnN0YWxsYXRpb25zQ29tcGF0TmFtZV06ICdmaXJlLWlpZC1jb21wYXQnLFxuICBbbWVzc2FnaW5nTmFtZV06ICdmaXJlLWZjbScsXG4gIFttZXNzYWdpbmdDb21wYXROYW1lXTogJ2ZpcmUtZmNtLWNvbXBhdCcsXG4gIFtwZXJmb3JtYW5jZU5hbWVdOiAnZmlyZS1wZXJmJyxcbiAgW3BlcmZvcm1hbmNlQ29tcGF0TmFtZV06ICdmaXJlLXBlcmYtY29tcGF0JyxcbiAgW3JlbW90ZUNvbmZpZ05hbWVdOiAnZmlyZS1yYycsXG4gIFtyZW1vdGVDb25maWdDb21wYXROYW1lXTogJ2ZpcmUtcmMtY29tcGF0JyxcbiAgW3N0b3JhZ2VOYW1lXTogJ2ZpcmUtZ2NzJyxcbiAgW3N0b3JhZ2VDb21wYXROYW1lXTogJ2ZpcmUtZ2NzLWNvbXBhdCcsXG4gIFtmaXJlc3RvcmVOYW1lXTogJ2ZpcmUtZnN0JyxcbiAgW2ZpcmVzdG9yZUNvbXBhdE5hbWVdOiAnZmlyZS1mc3QtY29tcGF0JyxcbiAgW2FpTmFtZV06ICdmaXJlLXZlcnRleCcsXG4gICdmaXJlLWpzJzogJ2ZpcmUtanMnLCAvLyBQbGF0Zm9ybSBpZGVudGlmaWVyIGZvciBKUyBTREsuXG4gIFtwYWNrYWdlTmFtZV06ICdmaXJlLWpzLWFsbCdcbn0gYXMgY29uc3Q7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRmlyZWJhc2VBcHAsXG4gIEZpcmViYXNlQXBwU2V0dGluZ3MsXG4gIEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MsXG4gIEZpcmViYXNlT3B0aW9ucyxcbiAgRmlyZWJhc2VTZXJ2ZXJBcHBcbn0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBQcm92aWRlciwgTmFtZSB9IGZyb20gJ0BmaXJlYmFzZS9jb21wb25lbnQnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IHsgREVGQVVMVF9FTlRSWV9OQU1FIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgRmlyZWJhc2VBcHBJbXBsIH0gZnJvbSAnLi9maXJlYmFzZUFwcCc7XG5pbXBvcnQgeyBGaXJlYmFzZVNlcnZlckFwcEltcGwgfSBmcm9tICcuL2ZpcmViYXNlU2VydmVyQXBwJztcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IF9hcHBzID0gbmV3IE1hcDxzdHJpbmcsIEZpcmViYXNlQXBwPigpO1xuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgX3NlcnZlckFwcHMgPSBuZXcgTWFwPHN0cmluZywgRmlyZWJhc2VTZXJ2ZXJBcHA+KCk7XG5cbi8qKlxuICogUmVnaXN0ZXJlZCBjb21wb25lbnRzLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGNvbnN0IF9jb21wb25lbnRzID0gbmV3IE1hcDxzdHJpbmcsIENvbXBvbmVudDxhbnk+PigpO1xuXG4vKipcbiAqIEBwYXJhbSBjb21wb25lbnQgLSB0aGUgY29tcG9uZW50IGJlaW5nIGFkZGVkIHRvIHRoaXMgYXBwJ3MgY29udGFpbmVyXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfYWRkQ29tcG9uZW50PFQgZXh0ZW5kcyBOYW1lPihcbiAgYXBwOiBGaXJlYmFzZUFwcCxcbiAgY29tcG9uZW50OiBDb21wb25lbnQ8VD5cbik6IHZvaWQge1xuICB0cnkge1xuICAgIChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsKS5jb250YWluZXIuYWRkQ29tcG9uZW50KGNvbXBvbmVudCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsb2dnZXIuZGVidWcoXG4gICAgICBgQ29tcG9uZW50ICR7Y29tcG9uZW50Lm5hbWV9IGZhaWxlZCB0byByZWdpc3RlciB3aXRoIEZpcmViYXNlQXBwICR7YXBwLm5hbWV9YCxcbiAgICAgIGVcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2FkZE9yT3ZlcndyaXRlQ29tcG9uZW50KFxuICBhcHA6IEZpcmViYXNlQXBwLFxuICBjb21wb25lbnQ6IENvbXBvbmVudFxuKTogdm9pZCB7XG4gIChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsKS5jb250YWluZXIuYWRkT3JPdmVyd3JpdGVDb21wb25lbnQoY29tcG9uZW50KTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGNvbXBvbmVudCAtIHRoZSBjb21wb25lbnQgdG8gcmVnaXN0ZXJcbiAqIEByZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBjb21wb25lbnQgaXMgcmVnaXN0ZXJlZCBzdWNjZXNzZnVsbHlcbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9yZWdpc3RlckNvbXBvbmVudDxUIGV4dGVuZHMgTmFtZT4oXG4gIGNvbXBvbmVudDogQ29tcG9uZW50PFQ+XG4pOiBib29sZWFuIHtcbiAgY29uc3QgY29tcG9uZW50TmFtZSA9IGNvbXBvbmVudC5uYW1lO1xuICBpZiAoX2NvbXBvbmVudHMuaGFzKGNvbXBvbmVudE5hbWUpKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgYFRoZXJlIHdlcmUgbXVsdGlwbGUgYXR0ZW1wdHMgdG8gcmVnaXN0ZXIgY29tcG9uZW50ICR7Y29tcG9uZW50TmFtZX0uYFxuICAgICk7XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBfY29tcG9uZW50cy5zZXQoY29tcG9uZW50TmFtZSwgY29tcG9uZW50KTtcblxuICAvLyBhZGQgdGhlIGNvbXBvbmVudCB0byBleGlzdGluZyBhcHAgaW5zdGFuY2VzXG4gIGZvciAoY29uc3QgYXBwIG9mIF9hcHBzLnZhbHVlcygpKSB7XG4gICAgX2FkZENvbXBvbmVudChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsLCBjb21wb25lbnQpO1xuICB9XG5cbiAgZm9yIChjb25zdCBzZXJ2ZXJBcHAgb2YgX3NlcnZlckFwcHMudmFsdWVzKCkpIHtcbiAgICBfYWRkQ29tcG9uZW50KHNlcnZlckFwcCBhcyBGaXJlYmFzZVNlcnZlckFwcEltcGwsIGNvbXBvbmVudCk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGFwcCAtIEZpcmViYXNlQXBwIGluc3RhbmNlXG4gKiBAcGFyYW0gbmFtZSAtIHNlcnZpY2UgbmFtZVxuICpcbiAqIEByZXR1cm5zIHRoZSBwcm92aWRlciBmb3IgdGhlIHNlcnZpY2Ugd2l0aCB0aGUgbWF0Y2hpbmcgbmFtZVxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2dldFByb3ZpZGVyPFQgZXh0ZW5kcyBOYW1lPihcbiAgYXBwOiBGaXJlYmFzZUFwcCxcbiAgbmFtZTogVFxuKTogUHJvdmlkZXI8VD4ge1xuICBjb25zdCBoZWFydGJlYXRDb250cm9sbGVyID0gKGFwcCBhcyBGaXJlYmFzZUFwcEltcGwpLmNvbnRhaW5lclxuICAgIC5nZXRQcm92aWRlcignaGVhcnRiZWF0JylcbiAgICAuZ2V0SW1tZWRpYXRlKHsgb3B0aW9uYWw6IHRydWUgfSk7XG4gIGlmIChoZWFydGJlYXRDb250cm9sbGVyKSB7XG4gICAgdm9pZCBoZWFydGJlYXRDb250cm9sbGVyLnRyaWdnZXJIZWFydGJlYXQoKTtcbiAgfVxuICByZXR1cm4gKGFwcCBhcyBGaXJlYmFzZUFwcEltcGwpLmNvbnRhaW5lci5nZXRQcm92aWRlcihuYW1lKTtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGFwcCAtIEZpcmViYXNlQXBwIGluc3RhbmNlXG4gKiBAcGFyYW0gbmFtZSAtIHNlcnZpY2UgbmFtZVxuICogQHBhcmFtIGluc3RhbmNlSWRlbnRpZmllciAtIHNlcnZpY2UgaW5zdGFuY2UgaWRlbnRpZmllciBpbiBjYXNlIHRoZSBzZXJ2aWNlIHN1cHBvcnRzIG11bHRpcGxlIGluc3RhbmNlc1xuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX3JlbW92ZVNlcnZpY2VJbnN0YW5jZTxUIGV4dGVuZHMgTmFtZT4oXG4gIGFwcDogRmlyZWJhc2VBcHAsXG4gIG5hbWU6IFQsXG4gIGluc3RhbmNlSWRlbnRpZmllcjogc3RyaW5nID0gREVGQVVMVF9FTlRSWV9OQU1FXG4pOiB2b2lkIHtcbiAgX2dldFByb3ZpZGVyKGFwcCwgbmFtZSkuY2xlYXJJbnN0YW5jZShpbnN0YW5jZUlkZW50aWZpZXIpO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gb2JqIC0gYW4gb2JqZWN0IG9mIHR5cGUgRmlyZWJhc2VBcHAsIEZpcmViYXNlT3B0aW9ucyBvciBGaXJlYmFzZUFwcFNldHRpbmdzLlxuICpcbiAqIEByZXR1cm5zIHRydWUgaWYgdGhlIHByb3ZpZGUgb2JqZWN0IGlzIG9mIHR5cGUgRmlyZWJhc2VBcHAuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfaXNGaXJlYmFzZUFwcChcbiAgb2JqOiBGaXJlYmFzZUFwcCB8IEZpcmViYXNlT3B0aW9ucyB8IEZpcmViYXNlQXBwU2V0dGluZ3Ncbik6IG9iaiBpcyBGaXJlYmFzZUFwcCB7XG4gIHJldHVybiAob2JqIGFzIEZpcmViYXNlQXBwKS5vcHRpb25zICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBvYmogLSBhbiBvYmplY3Qgb2YgdHlwZSBGaXJlYmFzZUFwcCwgRmlyZWJhc2VPcHRpb25zIG9yIEZpcmViYXNlQXBwU2V0dGluZ3MuXG4gKlxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgcHJvdmlkZWQgb2JqZWN0IGlzIG9mIHR5cGUgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2lzRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncyhcbiAgb2JqOiBGaXJlYmFzZUFwcCB8IEZpcmViYXNlT3B0aW9ucyB8IEZpcmViYXNlQXBwU2V0dGluZ3Ncbik6IG9iaiBpcyBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzIHtcbiAgaWYgKF9pc0ZpcmViYXNlQXBwKG9iaikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIChcbiAgICAnYXV0aElkVG9rZW4nIGluIG9iaiB8fFxuICAgICdhcHBDaGVja1Rva2VuJyBpbiBvYmogfHxcbiAgICAncmVsZWFzZU9uRGVyZWYnIGluIG9iaiB8fFxuICAgICdhdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQnIGluIG9ialxuICApO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gb2JqIC0gYW4gb2JqZWN0IG9mIHR5cGUgRmlyZWJhc2VBcHAuXG4gKlxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgcHJvdmlkZWQgb2JqZWN0IGlzIG9mIHR5cGUgRmlyZWJhc2VTZXJ2ZXJBcHBJbXBsLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX2lzRmlyZWJhc2VTZXJ2ZXJBcHAoXG4gIG9iajogRmlyZWJhc2VBcHAgfCBGaXJlYmFzZVNlcnZlckFwcCB8IG51bGwgfCB1bmRlZmluZWRcbik6IG9iaiBpcyBGaXJlYmFzZVNlcnZlckFwcCB7XG4gIGlmIChvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIChvYmogYXMgRmlyZWJhc2VTZXJ2ZXJBcHApLnNldHRpbmdzICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogVGVzdCBvbmx5XG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfY2xlYXJDb21wb25lbnRzKCk6IHZvaWQge1xuICBfY29tcG9uZW50cy5jbGVhcigpO1xufVxuXG4vKipcbiAqIEV4cG9ydGVkIGluIG9yZGVyIHRvIGJlIHVzZWQgaW4gYXBwLWNvbXBhdCBwYWNrYWdlXG4gKi9cbmV4cG9ydCB7IERFRkFVTFRfRU5UUllfTkFNRSBhcyBfREVGQVVMVF9FTlRSWV9OQU1FIH07XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRXJyb3JGYWN0b3J5LCBFcnJvck1hcCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IGNvbnN0IGVudW0gQXBwRXJyb3Ige1xuICBOT19BUFAgPSAnbm8tYXBwJyxcbiAgQkFEX0FQUF9OQU1FID0gJ2JhZC1hcHAtbmFtZScsXG4gIERVUExJQ0FURV9BUFAgPSAnZHVwbGljYXRlLWFwcCcsXG4gIEFQUF9ERUxFVEVEID0gJ2FwcC1kZWxldGVkJyxcbiAgU0VSVkVSX0FQUF9ERUxFVEVEID0gJ3NlcnZlci1hcHAtZGVsZXRlZCcsXG4gIE5PX09QVElPTlMgPSAnbm8tb3B0aW9ucycsXG4gIElOVkFMSURfQVBQX0FSR1VNRU5UID0gJ2ludmFsaWQtYXBwLWFyZ3VtZW50JyxcbiAgSU5WQUxJRF9MT0dfQVJHVU1FTlQgPSAnaW52YWxpZC1sb2ctYXJndW1lbnQnLFxuICBJREJfT1BFTiA9ICdpZGItb3BlbicsXG4gIElEQl9HRVQgPSAnaWRiLWdldCcsXG4gIElEQl9XUklURSA9ICdpZGItc2V0JyxcbiAgSURCX0RFTEVURSA9ICdpZGItZGVsZXRlJyxcbiAgRklOQUxJWkFUSU9OX1JFR0lTVFJZX05PVF9TVVBQT1JURUQgPSAnZmluYWxpemF0aW9uLXJlZ2lzdHJ5LW5vdC1zdXBwb3J0ZWQnLFxuICBJTlZBTElEX1NFUlZFUl9BUFBfRU5WSVJPTk1FTlQgPSAnaW52YWxpZC1zZXJ2ZXItYXBwLWVudmlyb25tZW50J1xufVxuXG5jb25zdCBFUlJPUlM6IEVycm9yTWFwPEFwcEVycm9yPiA9IHtcbiAgW0FwcEVycm9yLk5PX0FQUF06XG4gICAgXCJObyBGaXJlYmFzZSBBcHAgJ3skYXBwTmFtZX0nIGhhcyBiZWVuIGNyZWF0ZWQgLSBcIiArXG4gICAgJ2NhbGwgaW5pdGlhbGl6ZUFwcCgpIGZpcnN0JyxcbiAgW0FwcEVycm9yLkJBRF9BUFBfTkFNRV06IFwiSWxsZWdhbCBBcHAgbmFtZTogJ3skYXBwTmFtZX0nXCIsXG4gIFtBcHBFcnJvci5EVVBMSUNBVEVfQVBQXTpcbiAgICBcIkZpcmViYXNlIEFwcCBuYW1lZCAneyRhcHBOYW1lfScgYWxyZWFkeSBleGlzdHMgd2l0aCBkaWZmZXJlbnQgb3B0aW9ucyBvciBjb25maWdcIixcbiAgW0FwcEVycm9yLkFQUF9ERUxFVEVEXTogXCJGaXJlYmFzZSBBcHAgbmFtZWQgJ3skYXBwTmFtZX0nIGFscmVhZHkgZGVsZXRlZFwiLFxuICBbQXBwRXJyb3IuU0VSVkVSX0FQUF9ERUxFVEVEXTogJ0ZpcmViYXNlIFNlcnZlciBBcHAgaGFzIGJlZW4gZGVsZXRlZCcsXG4gIFtBcHBFcnJvci5OT19PUFRJT05TXTpcbiAgICAnTmVlZCB0byBwcm92aWRlIG9wdGlvbnMsIHdoZW4gbm90IGJlaW5nIGRlcGxveWVkIHRvIGhvc3RpbmcgdmlhIHNvdXJjZS4nLFxuICBbQXBwRXJyb3IuSU5WQUxJRF9BUFBfQVJHVU1FTlRdOlxuICAgICdmaXJlYmFzZS57JGFwcE5hbWV9KCkgdGFrZXMgZWl0aGVyIG5vIGFyZ3VtZW50IG9yIGEgJyArXG4gICAgJ0ZpcmViYXNlIEFwcCBpbnN0YW5jZS4nLFxuICBbQXBwRXJyb3IuSU5WQUxJRF9MT0dfQVJHVU1FTlRdOlxuICAgICdGaXJzdCBhcmd1bWVudCB0byBgb25Mb2dgIG11c3QgYmUgbnVsbCBvciBhIGZ1bmN0aW9uLicsXG4gIFtBcHBFcnJvci5JREJfT1BFTl06XG4gICAgJ0Vycm9yIHRocm93biB3aGVuIG9wZW5pbmcgSW5kZXhlZERCLiBPcmlnaW5hbCBlcnJvcjogeyRvcmlnaW5hbEVycm9yTWVzc2FnZX0uJyxcbiAgW0FwcEVycm9yLklEQl9HRVRdOlxuICAgICdFcnJvciB0aHJvd24gd2hlbiByZWFkaW5nIGZyb20gSW5kZXhlZERCLiBPcmlnaW5hbCBlcnJvcjogeyRvcmlnaW5hbEVycm9yTWVzc2FnZX0uJyxcbiAgW0FwcEVycm9yLklEQl9XUklURV06XG4gICAgJ0Vycm9yIHRocm93biB3aGVuIHdyaXRpbmcgdG8gSW5kZXhlZERCLiBPcmlnaW5hbCBlcnJvcjogeyRvcmlnaW5hbEVycm9yTWVzc2FnZX0uJyxcbiAgW0FwcEVycm9yLklEQl9ERUxFVEVdOlxuICAgICdFcnJvciB0aHJvd24gd2hlbiBkZWxldGluZyBmcm9tIEluZGV4ZWREQi4gT3JpZ2luYWwgZXJyb3I6IHskb3JpZ2luYWxFcnJvck1lc3NhZ2V9LicsXG4gIFtBcHBFcnJvci5GSU5BTElaQVRJT05fUkVHSVNUUllfTk9UX1NVUFBPUlRFRF06XG4gICAgJ0ZpcmViYXNlU2VydmVyQXBwIGRlbGV0ZU9uRGVyZWYgZmllbGQgZGVmaW5lZCBidXQgdGhlIEpTIHJ1bnRpbWUgZG9lcyBub3Qgc3VwcG9ydCBGaW5hbGl6YXRpb25SZWdpc3RyeS4nLFxuICBbQXBwRXJyb3IuSU5WQUxJRF9TRVJWRVJfQVBQX0VOVklST05NRU5UXTpcbiAgICAnRmlyZWJhc2VTZXJ2ZXJBcHAgaXMgbm90IGZvciB1c2UgaW4gYnJvd3NlciBlbnZpcm9ubWVudHMuJ1xufTtcblxuaW50ZXJmYWNlIEVycm9yUGFyYW1zIHtcbiAgW0FwcEVycm9yLk5PX0FQUF06IHsgYXBwTmFtZTogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5CQURfQVBQX05BTUVdOiB7IGFwcE5hbWU6IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuRFVQTElDQVRFX0FQUF06IHsgYXBwTmFtZTogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5BUFBfREVMRVRFRF06IHsgYXBwTmFtZTogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5JTlZBTElEX0FQUF9BUkdVTUVOVF06IHsgYXBwTmFtZTogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5JREJfT1BFTl06IHsgb3JpZ2luYWxFcnJvck1lc3NhZ2U/OiBzdHJpbmcgfTtcbiAgW0FwcEVycm9yLklEQl9HRVRdOiB7IG9yaWdpbmFsRXJyb3JNZXNzYWdlPzogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5JREJfV1JJVEVdOiB7IG9yaWdpbmFsRXJyb3JNZXNzYWdlPzogc3RyaW5nIH07XG4gIFtBcHBFcnJvci5JREJfREVMRVRFXTogeyBvcmlnaW5hbEVycm9yTWVzc2FnZT86IHN0cmluZyB9O1xuICBbQXBwRXJyb3IuRklOQUxJWkFUSU9OX1JFR0lTVFJZX05PVF9TVVBQT1JURURdOiB7IGFwcE5hbWU/OiBzdHJpbmcgfTtcbn1cblxuZXhwb3J0IGNvbnN0IEVSUk9SX0ZBQ1RPUlkgPSBuZXcgRXJyb3JGYWN0b3J5PEFwcEVycm9yLCBFcnJvclBhcmFtcz4oXG4gICdhcHAnLFxuICAnRmlyZWJhc2UnLFxuICBFUlJPUlNcbik7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRmlyZWJhc2VBcHAsXG4gIEZpcmViYXNlT3B0aW9ucyxcbiAgRmlyZWJhc2VBcHBTZXR0aW5nc1xufSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQge1xuICBDb21wb25lbnRDb250YWluZXIsXG4gIENvbXBvbmVudCxcbiAgQ29tcG9uZW50VHlwZVxufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IEVSUk9SX0ZBQ1RPUlksIEFwcEVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuXG5leHBvcnQgY2xhc3MgRmlyZWJhc2VBcHBJbXBsIGltcGxlbWVudHMgRmlyZWJhc2VBcHAge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX29wdGlvbnM6IEZpcmViYXNlT3B0aW9ucztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9uYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBPcmlnaW5hbCBjb25maWcgdmFsdWVzIHBhc3NlZCBpbiBhcyBhIGNvbnN0cnVjdG9yIHBhcmFtZXRlci5cbiAgICogSXQgaXMgb25seSB1c2VkIHRvIGNvbXBhcmUgd2l0aCBhbm90aGVyIGNvbmZpZyBvYmplY3QgdG8gc3VwcG9ydCBpZGVtcG90ZW50IGluaXRpYWxpemVBcHAoKS5cbiAgICpcbiAgICogVXBkYXRpbmcgYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkIG9uIHRoZSBBcHAgaW5zdGFuY2Ugd2lsbCBub3QgY2hhbmdlIGl0cyB2YWx1ZSBpbiBfY29uZmlnLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfY29uZmlnOiBSZXF1aXJlZDxGaXJlYmFzZUFwcFNldHRpbmdzPjtcbiAgcHJpdmF0ZSBfYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkOiBib29sZWFuO1xuICBwcm90ZWN0ZWQgX2lzRGVsZXRlZCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWRvbmx5IF9jb250YWluZXI6IENvbXBvbmVudENvbnRhaW5lcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBvcHRpb25zOiBGaXJlYmFzZU9wdGlvbnMsXG4gICAgY29uZmlnOiBSZXF1aXJlZDxGaXJlYmFzZUFwcFNldHRpbmdzPixcbiAgICBjb250YWluZXI6IENvbXBvbmVudENvbnRhaW5lclxuICApIHtcbiAgICB0aGlzLl9vcHRpb25zID0geyAuLi5vcHRpb25zIH07XG4gICAgdGhpcy5fY29uZmlnID0geyAuLi5jb25maWcgfTtcbiAgICB0aGlzLl9uYW1lID0gY29uZmlnLm5hbWU7XG4gICAgdGhpcy5fYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkID1cbiAgICAgIGNvbmZpZy5hdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQ7XG4gICAgdGhpcy5fY29udGFpbmVyID0gY29udGFpbmVyO1xuICAgIHRoaXMuY29udGFpbmVyLmFkZENvbXBvbmVudChcbiAgICAgIG5ldyBDb21wb25lbnQoJ2FwcCcsICgpID0+IHRoaXMsIENvbXBvbmVudFR5cGUuUFVCTElDKVxuICAgICk7XG4gIH1cblxuICBnZXQgYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgIHRoaXMuY2hlY2tEZXN0cm95ZWQoKTtcbiAgICByZXR1cm4gdGhpcy5fYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkO1xuICB9XG5cbiAgc2V0IGF1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCh2YWw6IGJvb2xlYW4pIHtcbiAgICB0aGlzLmNoZWNrRGVzdHJveWVkKCk7XG4gICAgdGhpcy5fYXV0b21hdGljRGF0YUNvbGxlY3Rpb25FbmFibGVkID0gdmFsO1xuICB9XG5cbiAgZ2V0IG5hbWUoKTogc3RyaW5nIHtcbiAgICB0aGlzLmNoZWNrRGVzdHJveWVkKCk7XG4gICAgcmV0dXJuIHRoaXMuX25hbWU7XG4gIH1cblxuICBnZXQgb3B0aW9ucygpOiBGaXJlYmFzZU9wdGlvbnMge1xuICAgIHRoaXMuY2hlY2tEZXN0cm95ZWQoKTtcbiAgICByZXR1cm4gdGhpcy5fb3B0aW9ucztcbiAgfVxuXG4gIGdldCBjb25maWcoKTogUmVxdWlyZWQ8RmlyZWJhc2VBcHBTZXR0aW5ncz4ge1xuICAgIHRoaXMuY2hlY2tEZXN0cm95ZWQoKTtcbiAgICByZXR1cm4gdGhpcy5fY29uZmlnO1xuICB9XG5cbiAgZ2V0IGNvbnRhaW5lcigpOiBDb21wb25lbnRDb250YWluZXIge1xuICAgIHJldHVybiB0aGlzLl9jb250YWluZXI7XG4gIH1cblxuICBnZXQgaXNEZWxldGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9pc0RlbGV0ZWQ7XG4gIH1cblxuICBzZXQgaXNEZWxldGVkKHZhbDogYm9vbGVhbikge1xuICAgIHRoaXMuX2lzRGVsZXRlZCA9IHZhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgdGhyb3cgYW4gRXJyb3IgaWYgdGhlIEFwcCBoYXMgYWxyZWFkeSBiZWVuIGRlbGV0ZWQgLVxuICAgKiB1c2UgYmVmb3JlIHBlcmZvcm1pbmcgQVBJIGFjdGlvbnMgb24gdGhlIEFwcC5cbiAgICovXG4gIHByb3RlY3RlZCBjaGVja0Rlc3Ryb3llZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0RlbGV0ZWQpIHtcbiAgICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLkFQUF9ERUxFVEVELCB7IGFwcE5hbWU6IHRoaXMuX25hbWUgfSk7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRmlyZWJhc2VBcHBTZXR0aW5ncyxcbiAgRmlyZWJhc2VTZXJ2ZXJBcHAsXG4gIEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MsXG4gIEZpcmViYXNlT3B0aW9uc1xufSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgeyBkZWxldGVBcHAsIHJlZ2lzdGVyVmVyc2lvbiB9IGZyb20gJy4vYXBpJztcbmltcG9ydCB7IENvbXBvbmVudENvbnRhaW5lciB9IGZyb20gJ0BmaXJlYmFzZS9jb21wb25lbnQnO1xuaW1wb3J0IHsgRmlyZWJhc2VBcHBJbXBsIH0gZnJvbSAnLi9maXJlYmFzZUFwcCc7XG5pbXBvcnQgeyBFUlJPUl9GQUNUT1JZLCBBcHBFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IG5hbWUgYXMgcGFja2FnZU5hbWUsIHZlcnNpb24gfSBmcm9tICcuLi9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgYmFzZTY0RGVjb2RlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vLyBQYXJzZSB0aGUgdG9rZW4gYW5kIGNoZWNrIHRvIHNlZSBpZiB0aGUgYGV4cGAgY2xhaW0gaXMgaW4gdGhlIGZ1dHVyZS5cbi8vIFJlcG9ydHMgYW4gZXJyb3IgdG8gdGhlIGNvbnNvbGUgaWYgdGhlIHRva2VuIG9yIGNsYWltIGNvdWxkIG5vdCBiZSBwYXJzZWQsIG9yIGlmIGBleHBgIGlzIGluXG4vLyB0aGUgcGFzdC5cbmZ1bmN0aW9uIHZhbGlkYXRlVG9rZW5UVEwoYmFzZTY0VG9rZW46IHN0cmluZywgdG9rZW5OYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3Qgc2Vjb25kUGFydCA9IGJhc2U2NERlY29kZShiYXNlNjRUb2tlbi5zcGxpdCgnLicpWzFdKTtcbiAgaWYgKHNlY29uZFBhcnQgPT09IG51bGwpIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgYEZpcmViYXNlU2VydmVyQXBwICR7dG9rZW5OYW1lfSBpcyBpbnZhbGlkOiBzZWNvbmQgcGFydCBjb3VsZCBub3QgYmUgcGFyc2VkLmBcbiAgICApO1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBleHBDbGFpbSA9IEpTT04ucGFyc2Uoc2Vjb25kUGFydCkuZXhwO1xuICBpZiAoZXhwQ2xhaW0gPT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBgRmlyZWJhc2VTZXJ2ZXJBcHAgJHt0b2tlbk5hbWV9IGlzIGludmFsaWQ6IGV4cGlyYXRpb24gY2xhaW0gY291bGQgbm90IGJlIHBhcnNlZGBcbiAgICApO1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBleHAgPSBKU09OLnBhcnNlKHNlY29uZFBhcnQpLmV4cCAqIDEwMDA7XG4gIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICBjb25zdCBkaWZmID0gZXhwIC0gbm93O1xuICBpZiAoZGlmZiA8PSAwKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIGBGaXJlYmFzZVNlcnZlckFwcCAke3Rva2VuTmFtZX0gaXMgaW52YWxpZDogdGhlIHRva2VuIGhhcyBleHBpcmVkLmBcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBGaXJlYmFzZVNlcnZlckFwcEltcGxcbiAgZXh0ZW5kcyBGaXJlYmFzZUFwcEltcGxcbiAgaW1wbGVtZW50cyBGaXJlYmFzZVNlcnZlckFwcFxue1xuICBwcml2YXRlIHJlYWRvbmx5IF9zZXJ2ZXJDb25maWc6IEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3M7XG4gIHByaXZhdGUgX2ZpbmFsaXphdGlvblJlZ2lzdHJ5OiBGaW5hbGl6YXRpb25SZWdpc3RyeTxvYmplY3Q+IHwgbnVsbDtcbiAgcHJpdmF0ZSBfcmVmQ291bnQ6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBvcHRpb25zOiBGaXJlYmFzZU9wdGlvbnMgfCBGaXJlYmFzZUFwcEltcGwsXG4gICAgc2VydmVyQ29uZmlnOiBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBjb250YWluZXI6IENvbXBvbmVudENvbnRhaW5lclxuICApIHtcbiAgICAvLyBCdWlsZCBjb25maWd1cmF0aW9uIHBhcmFtZXRlcnMgZm9yIHRoZSBGaXJlYmFzZUFwcEltcGwgYmFzZSBjbGFzcy5cbiAgICBjb25zdCBhdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQgPVxuICAgICAgc2VydmVyQ29uZmlnLmF1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCAhPT0gdW5kZWZpbmVkXG4gICAgICAgID8gc2VydmVyQ29uZmlnLmF1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZFxuICAgICAgICA6IHRydWU7XG5cbiAgICAvLyBDcmVhdGUgdGhlIEZpcmViYXNlQXBwU2V0dGluZ3Mgb2JqZWN0IGZvciB0aGUgRmlyZWJhc2VBcHBJbXAgY29uc3RydWN0b3IuXG4gICAgY29uc3QgY29uZmlnOiBSZXF1aXJlZDxGaXJlYmFzZUFwcFNldHRpbmdzPiA9IHtcbiAgICAgIG5hbWUsXG4gICAgICBhdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWRcbiAgICB9O1xuXG4gICAgaWYgKChvcHRpb25zIGFzIEZpcmViYXNlT3B0aW9ucykuYXBpS2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIENvbnN0cnVjdCB0aGUgcGFyZW50IEZpcmViYXNlQXBwSW1wIG9iamVjdC5cbiAgICAgIHN1cGVyKG9wdGlvbnMgYXMgRmlyZWJhc2VPcHRpb25zLCBjb25maWcsIGNvbnRhaW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGFwcEltcGw6IEZpcmViYXNlQXBwSW1wbCA9IG9wdGlvbnMgYXMgRmlyZWJhc2VBcHBJbXBsO1xuICAgICAgc3VwZXIoYXBwSW1wbC5vcHRpb25zLCBjb25maWcsIGNvbnRhaW5lcik7XG4gICAgfVxuXG4gICAgLy8gTm93IGNvbnN0cnVjdCB0aGUgZGF0YSBmb3IgdGhlIEZpcmViYXNlU2VydmVyQXBwSW1wbC5cbiAgICB0aGlzLl9zZXJ2ZXJDb25maWcgPSB7XG4gICAgICBhdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQsXG4gICAgICAuLi5zZXJ2ZXJDb25maWdcbiAgICB9O1xuXG4gICAgLy8gRW5zdXJlIHRoYXQgdGhlIGN1cnJlbnQgdGltZSBpcyB3aXRoaW4gdGhlIGBhdXRoSWR0b2tlbmAgd2luZG93IG9mIHZhbGlkaXR5LlxuICAgIGlmICh0aGlzLl9zZXJ2ZXJDb25maWcuYXV0aElkVG9rZW4pIHtcbiAgICAgIHZhbGlkYXRlVG9rZW5UVEwodGhpcy5fc2VydmVyQ29uZmlnLmF1dGhJZFRva2VuLCAnYXV0aElkVG9rZW4nKTtcbiAgICB9XG5cbiAgICAvLyBFbnN1cmUgdGhhdCB0aGUgY3VycmVudCB0aW1lIGlzIHdpdGhpbiB0aGUgYGFwcENoZWNrVG9rZW5gIHdpbmRvdyBvZiB2YWxpZGl0eS5cbiAgICBpZiAodGhpcy5fc2VydmVyQ29uZmlnLmFwcENoZWNrVG9rZW4pIHtcbiAgICAgIHZhbGlkYXRlVG9rZW5UVEwodGhpcy5fc2VydmVyQ29uZmlnLmFwcENoZWNrVG9rZW4sICdhcHBDaGVja1Rva2VuJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fZmluYWxpemF0aW9uUmVnaXN0cnkgPSBudWxsO1xuICAgIGlmICh0eXBlb2YgRmluYWxpemF0aW9uUmVnaXN0cnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLl9maW5hbGl6YXRpb25SZWdpc3RyeSA9IG5ldyBGaW5hbGl6YXRpb25SZWdpc3RyeSgoKSA9PiB7XG4gICAgICAgIHRoaXMuYXV0b21hdGljQ2xlYW51cCgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5fcmVmQ291bnQgPSAwO1xuICAgIHRoaXMuaW5jUmVmQ291bnQodGhpcy5fc2VydmVyQ29uZmlnLnJlbGVhc2VPbkRlcmVmKTtcblxuICAgIC8vIERvIG5vdCByZXRhaW4gYSBoYXJkIHJlZmVyZW5jZSB0byB0aGUgZHJlZiBvYmplY3QsIG90aGVyd2lzZSB0aGUgRmluYWxpemF0aW9uUmVnaXN0cnlcbiAgICAvLyB3aWxsIG5ldmVyIHRyaWdnZXIuXG4gICAgdGhpcy5fc2VydmVyQ29uZmlnLnJlbGVhc2VPbkRlcmVmID0gdW5kZWZpbmVkO1xuICAgIHNlcnZlckNvbmZpZy5yZWxlYXNlT25EZXJlZiA9IHVuZGVmaW5lZDtcblxuICAgIHJlZ2lzdGVyVmVyc2lvbihwYWNrYWdlTmFtZSwgdmVyc2lvbiwgJ3NlcnZlcmFwcCcpO1xuICB9XG5cbiAgdG9KU09OKCk6IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGdldCByZWZDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9yZWZDb3VudDtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCB0aGUgcmVmZXJlbmNlIGNvdW50IG9mIHRoaXMgc2VydmVyIGFwcC4gSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkLCByZWdpc3RlciBpdFxuICAvLyB3aXRoIHRoZSBmaW5hbGl6YXRpb24gcmVnaXN0cnkuXG4gIGluY1JlZkNvdW50KG9iajogb2JqZWN0IHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNEZWxldGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX3JlZkNvdW50Kys7XG4gICAgaWYgKG9iaiAhPT0gdW5kZWZpbmVkICYmIHRoaXMuX2ZpbmFsaXphdGlvblJlZ2lzdHJ5ICE9PSBudWxsKSB7XG4gICAgICB0aGlzLl9maW5hbGl6YXRpb25SZWdpc3RyeS5yZWdpc3RlcihvYmosIHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIERlY3JlbWVudCB0aGUgcmVmZXJlbmNlIGNvdW50LlxuICBkZWNSZWZDb3VudCgpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmlzRGVsZXRlZCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHJldHVybiAtLXRoaXMuX3JlZkNvdW50O1xuICB9XG5cbiAgLy8gSW52b2tlZCBieSB0aGUgRmluYWxpemF0aW9uUmVnaXN0cnkgY2FsbGJhY2sgdG8gbm90ZSB0aGF0IHRoaXMgYXBwIHNob3VsZCBnbyB0aHJvdWdoIGl0c1xuICAvLyByZWZlcmVuY2UgY291bnRzIGFuZCBkZWxldGUgaXRzZWxmIGlmIG5vIHJlZmVyZW5jZSBjb3VudCByZW1haW4uIFRoZSBjb29yZGluYXRpbmcgbG9naWMgdGhhdFxuICAvLyBoYW5kbGVzIHRoaXMgaXMgaW4gZGVsZXRlQXBwKC4uLikuXG4gIHByaXZhdGUgYXV0b21hdGljQ2xlYW51cCgpOiB2b2lkIHtcbiAgICB2b2lkIGRlbGV0ZUFwcCh0aGlzKTtcbiAgfVxuXG4gIGdldCBzZXR0aW5ncygpOiBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzIHtcbiAgICB0aGlzLmNoZWNrRGVzdHJveWVkKCk7XG4gICAgcmV0dXJuIHRoaXMuX3NlcnZlckNvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgdGhyb3cgYW4gRXJyb3IgaWYgdGhlIEFwcCBoYXMgYWxyZWFkeSBiZWVuIGRlbGV0ZWQgLVxuICAgKiB1c2UgYmVmb3JlIHBlcmZvcm1pbmcgQVBJIGFjdGlvbnMgb24gdGhlIEFwcC5cbiAgICovXG4gIHByb3RlY3RlZCBjaGVja0Rlc3Ryb3llZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0RlbGV0ZWQpIHtcbiAgICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLlNFUlZFUl9BUFBfREVMRVRFRCk7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRmlyZWJhc2VBcHAsXG4gIEZpcmViYXNlU2VydmVyQXBwLFxuICBGaXJlYmFzZU9wdGlvbnMsXG4gIEZpcmViYXNlQXBwU2V0dGluZ3MsXG4gIEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3Ncbn0gZnJvbSAnLi9wdWJsaWMtdHlwZXMnO1xuaW1wb3J0IHsgREVGQVVMVF9FTlRSWV9OQU1FLCBQTEFURk9STV9MT0dfU1RSSU5HIH0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgRVJST1JfRkFDVE9SWSwgQXBwRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQge1xuICBDb21wb25lbnRDb250YWluZXIsXG4gIENvbXBvbmVudCxcbiAgTmFtZSxcbiAgQ29tcG9uZW50VHlwZVxufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IHZlcnNpb24gfSBmcm9tICcuLi8uLi9maXJlYmFzZS9wYWNrYWdlLmpzb24nO1xuaW1wb3J0IHsgRmlyZWJhc2VBcHBJbXBsIH0gZnJvbSAnLi9maXJlYmFzZUFwcCc7XG5pbXBvcnQgeyBGaXJlYmFzZVNlcnZlckFwcEltcGwgfSBmcm9tICcuL2ZpcmViYXNlU2VydmVyQXBwJztcbmltcG9ydCB7XG4gIF9hcHBzLFxuICBfY29tcG9uZW50cyxcbiAgX2lzRmlyZWJhc2VBcHAsXG4gIF9pc0ZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MsXG4gIF9yZWdpc3RlckNvbXBvbmVudCxcbiAgX3NlcnZlckFwcHNcbn0gZnJvbSAnLi9pbnRlcm5hbCc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQge1xuICBMb2dMZXZlbFN0cmluZyxcbiAgc2V0TG9nTGV2ZWwgYXMgc2V0TG9nTGV2ZWxJbXBsLFxuICBMb2dDYWxsYmFjayxcbiAgTG9nT3B0aW9ucyxcbiAgc2V0VXNlckxvZ0hhbmRsZXJcbn0gZnJvbSAnQGZpcmViYXNlL2xvZ2dlcic7XG5pbXBvcnQge1xuICBkZWVwRXF1YWwsXG4gIGdldERlZmF1bHRBcHBDb25maWcsXG4gIGlzQnJvd3NlcixcbiAgaXNXZWJXb3JrZXJcbn0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5leHBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vKipcbiAqIFRoZSBjdXJyZW50IFNESyB2ZXJzaW9uLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IFNES19WRVJTSU9OID0gdmVyc2lvbjtcblxuLyoqXG4gKiBDcmVhdGVzIGFuZCBpbml0aWFsaXplcyBhIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlQXBwfSBpbnN0YW5jZS5cbiAqXG4gKiBTZWVcbiAqIHtAbGlua1xuICogICBodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy93ZWIvc2V0dXAjYWRkX2ZpcmViYXNlX3RvX3lvdXJfYXBwXG4gKiAgIHwgQWRkIEZpcmViYXNlIHRvIHlvdXIgYXBwfSBhbmRcbiAqIHtAbGlua1xuICogICBodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy93ZWIvc2V0dXAjbXVsdGlwbGUtcHJvamVjdHNcbiAqICAgfCBJbml0aWFsaXplIG11bHRpcGxlIHByb2plY3RzfSBmb3IgZGV0YWlsZWQgZG9jdW1lbnRhdGlvbi5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICpcbiAqIC8vIEluaXRpYWxpemUgZGVmYXVsdCBhcHBcbiAqIC8vIFJldHJpZXZlIHlvdXIgb3duIG9wdGlvbnMgdmFsdWVzIGJ5IGFkZGluZyBhIHdlYiBhcHAgb25cbiAqIC8vIGh0dHBzOi8vY29uc29sZS5maXJlYmFzZS5nb29nbGUuY29tXG4gKiBpbml0aWFsaXplQXBwKHtcbiAqICAgYXBpS2V5OiBcIkFJemEuLi4uXCIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBdXRoIC8gR2VuZXJhbCBVc2VcbiAqICAgYXV0aERvbWFpbjogXCJZT1VSX0FQUC5maXJlYmFzZWFwcC5jb21cIiwgICAgICAgICAvLyBBdXRoIHdpdGggcG9wdXAvcmVkaXJlY3RcbiAqICAgZGF0YWJhc2VVUkw6IFwiaHR0cHM6Ly9ZT1VSX0FQUC5maXJlYmFzZWlvLmNvbVwiLCAvLyBSZWFsdGltZSBEYXRhYmFzZVxuICogICBzdG9yYWdlQnVja2V0OiBcIllPVVJfQVBQLmFwcHNwb3QuY29tXCIsICAgICAgICAgIC8vIFN0b3JhZ2VcbiAqICAgbWVzc2FnaW5nU2VuZGVySWQ6IFwiMTIzNDU2Nzg5XCIgICAgICAgICAgICAgICAgICAvLyBDbG91ZCBNZXNzYWdpbmdcbiAqIH0pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqXG4gKiAvLyBJbml0aWFsaXplIGFub3RoZXIgYXBwXG4gKiBjb25zdCBvdGhlckFwcCA9IGluaXRpYWxpemVBcHAoe1xuICogICBkYXRhYmFzZVVSTDogXCJodHRwczovLzxPVEhFUl9EQVRBQkFTRV9OQU1FPi5maXJlYmFzZWlvLmNvbVwiLFxuICogICBzdG9yYWdlQnVja2V0OiBcIjxPVEhFUl9TVE9SQUdFX0JVQ0tFVD4uYXBwc3BvdC5jb21cIlxuICogfSwgXCJvdGhlckFwcFwiKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyB0byBjb25maWd1cmUgdGhlIGFwcCdzIHNlcnZpY2VzLlxuICogQHBhcmFtIG5hbWUgLSBPcHRpb25hbCBuYW1lIG9mIHRoZSBhcHAgdG8gaW5pdGlhbGl6ZS4gSWYgbm8gbmFtZVxuICogICBpcyBwcm92aWRlZCwgdGhlIGRlZmF1bHQgaXMgYFwiW0RFRkFVTFRdXCJgLlxuICpcbiAqIEByZXR1cm5zIFRoZSBpbml0aWFsaXplZCBhcHAuXG4gKlxuICogQHRocm93cyBJZiB0aGUgb3B0aW9uYWwgYG5hbWVgIHBhcmFtZXRlciBpcyBtYWxmb3JtZWQgb3IgZW1wdHkuXG4gKlxuICogQHRocm93cyBJZiBhIGBGaXJlYmFzZUFwcGAgYWxyZWFkeSBleGlzdHMgd2l0aCB0aGUgc2FtZSBuYW1lIGJ1dCB3aXRoIGEgZGlmZmVyZW50IGNvbmZpZ3VyYXRpb24uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZUFwcChcbiAgb3B0aW9uczogRmlyZWJhc2VPcHRpb25zLFxuICBuYW1lPzogc3RyaW5nXG4pOiBGaXJlYmFzZUFwcDtcbi8qKlxuICogQ3JlYXRlcyBhbmQgaW5pdGlhbGl6ZXMgYSBGaXJlYmFzZUFwcCBpbnN0YW5jZS5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgdG8gY29uZmlndXJlIHRoZSBhcHAncyBzZXJ2aWNlcy5cbiAqIEBwYXJhbSBjb25maWcgLSBGaXJlYmFzZUFwcCBDb25maWd1cmF0aW9uXG4gKlxuICogQHRocm93cyBJZiB7QGxpbmsgRmlyZWJhc2VBcHBTZXR0aW5ncy5uYW1lfSBpcyBkZWZpbmVkIGJ1dCB0aGUgdmFsdWUgaXMgbWFsZm9ybWVkIG9yIGVtcHR5LlxuICpcbiAqIEB0aHJvd3MgSWYgYSBgRmlyZWJhc2VBcHBgIGFscmVhZHkgZXhpc3RzIHdpdGggdGhlIHNhbWUgbmFtZSBidXQgd2l0aCBhIGRpZmZlcmVudCBjb25maWd1cmF0aW9uLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZUFwcChcbiAgb3B0aW9uczogRmlyZWJhc2VPcHRpb25zLFxuICBjb25maWc/OiBGaXJlYmFzZUFwcFNldHRpbmdzXG4pOiBGaXJlYmFzZUFwcDtcbi8qKlxuICogQ3JlYXRlcyBhbmQgaW5pdGlhbGl6ZXMgYSBGaXJlYmFzZUFwcCBpbnN0YW5jZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplQXBwKCk6IEZpcmViYXNlQXBwO1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVBcHAoXG4gIF9vcHRpb25zPzogRmlyZWJhc2VPcHRpb25zLFxuICByYXdDb25maWcgPSB7fVxuKTogRmlyZWJhc2VBcHAge1xuICBsZXQgb3B0aW9ucyA9IF9vcHRpb25zO1xuXG4gIGlmICh0eXBlb2YgcmF3Q29uZmlnICE9PSAnb2JqZWN0Jykge1xuICAgIGNvbnN0IG5hbWUgPSByYXdDb25maWc7XG4gICAgcmF3Q29uZmlnID0geyBuYW1lIH07XG4gIH1cblxuICBjb25zdCBjb25maWc6IFJlcXVpcmVkPEZpcmViYXNlQXBwU2V0dGluZ3M+ID0ge1xuICAgIG5hbWU6IERFRkFVTFRfRU5UUllfTkFNRSxcbiAgICBhdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQ6IHRydWUsXG4gICAgLi4ucmF3Q29uZmlnXG4gIH07XG4gIGNvbnN0IG5hbWUgPSBjb25maWcubmFtZTtcblxuICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnIHx8ICFuYW1lKSB7XG4gICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuQkFEX0FQUF9OQU1FLCB7XG4gICAgICBhcHBOYW1lOiBTdHJpbmcobmFtZSlcbiAgICB9KTtcbiAgfVxuXG4gIG9wdGlvbnMgfHw9IGdldERlZmF1bHRBcHBDb25maWcoKTtcblxuICBpZiAoIW9wdGlvbnMpIHtcbiAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5OT19PUFRJT05TKTtcbiAgfVxuXG4gIGNvbnN0IGV4aXN0aW5nQXBwID0gX2FwcHMuZ2V0KG5hbWUpIGFzIEZpcmViYXNlQXBwSW1wbDtcbiAgaWYgKGV4aXN0aW5nQXBwKSB7XG4gICAgLy8gcmV0dXJuIHRoZSBleGlzdGluZyBhcHAgaWYgb3B0aW9ucyBhbmQgY29uZmlnIGRlZXAgZXF1YWwgdGhlIG9uZXMgaW4gdGhlIGV4aXN0aW5nIGFwcC5cbiAgICBpZiAoXG4gICAgICBkZWVwRXF1YWwob3B0aW9ucywgZXhpc3RpbmdBcHAub3B0aW9ucykgJiZcbiAgICAgIGRlZXBFcXVhbChjb25maWcsIGV4aXN0aW5nQXBwLmNvbmZpZylcbiAgICApIHtcbiAgICAgIHJldHVybiBleGlzdGluZ0FwcDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuRFVQTElDQVRFX0FQUCwgeyBhcHBOYW1lOiBuYW1lIH0pO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGNvbnRhaW5lciA9IG5ldyBDb21wb25lbnRDb250YWluZXIobmFtZSk7XG4gIGZvciAoY29uc3QgY29tcG9uZW50IG9mIF9jb21wb25lbnRzLnZhbHVlcygpKSB7XG4gICAgY29udGFpbmVyLmFkZENvbXBvbmVudChjb21wb25lbnQpO1xuICB9XG5cbiAgY29uc3QgbmV3QXBwID0gbmV3IEZpcmViYXNlQXBwSW1wbChvcHRpb25zLCBjb25maWcsIGNvbnRhaW5lcik7XG5cbiAgX2FwcHMuc2V0KG5hbWUsIG5ld0FwcCk7XG5cbiAgcmV0dXJuIG5ld0FwcDtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuZCBpbml0aWFsaXplcyBhIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfSBpbnN0YW5jZS5cbiAqXG4gKiBUaGUgYEZpcmViYXNlU2VydmVyQXBwYCBpcyBzaW1pbGFyIHRvIGBGaXJlYmFzZUFwcGAsIGJ1dCBpcyBpbnRlbmRlZCBmb3IgZXhlY3V0aW9uIGluXG4gKiBzZXJ2ZXIgc2lkZSByZW5kZXJpbmcgZW52aXJvbm1lbnRzIG9ubHkuIEluaXRpYWxpemF0aW9uIHdpbGwgZmFpbCBpZiBpbnZva2VkIGZyb20gYVxuICogYnJvd3NlciBlbnZpcm9ubWVudC5cbiAqXG4gKiBTZWVcbiAqIHtAbGlua1xuICogICBodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy93ZWIvc2V0dXAjYWRkX2ZpcmViYXNlX3RvX3lvdXJfYXBwXG4gKiAgIHwgQWRkIEZpcmViYXNlIHRvIHlvdXIgYXBwfSBhbmRcbiAqIHtAbGlua1xuICogICBodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy93ZWIvc2V0dXAjbXVsdGlwbGUtcHJvamVjdHNcbiAqICAgfCBJbml0aWFsaXplIG11bHRpcGxlIHByb2plY3RzfSBmb3IgZGV0YWlsZWQgZG9jdW1lbnRhdGlvbi5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICpcbiAqIC8vIEluaXRpYWxpemUgYW4gaW5zdGFuY2Ugb2YgYEZpcmViYXNlU2VydmVyQXBwYC5cbiAqIC8vIFJldHJpZXZlIHlvdXIgb3duIG9wdGlvbnMgdmFsdWVzIGJ5IGFkZGluZyBhIHdlYiBhcHAgb25cbiAqIC8vIGh0dHBzOi8vY29uc29sZS5maXJlYmFzZS5nb29nbGUuY29tXG4gKiBpbml0aWFsaXplU2VydmVyQXBwKHtcbiAqICAgICBhcGlLZXk6IFwiQUl6YS4uLi5cIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF1dGggLyBHZW5lcmFsIFVzZVxuICogICAgIGF1dGhEb21haW46IFwiWU9VUl9BUFAuZmlyZWJhc2VhcHAuY29tXCIsICAgICAgICAgLy8gQXV0aCB3aXRoIHBvcHVwL3JlZGlyZWN0XG4gKiAgICAgZGF0YWJhc2VVUkw6IFwiaHR0cHM6Ly9ZT1VSX0FQUC5maXJlYmFzZWlvLmNvbVwiLCAvLyBSZWFsdGltZSBEYXRhYmFzZVxuICogICAgIHN0b3JhZ2VCdWNrZXQ6IFwiWU9VUl9BUFAuYXBwc3BvdC5jb21cIiwgICAgICAgICAgLy8gU3RvcmFnZVxuICogICAgIG1lc3NhZ2luZ1NlbmRlcklkOiBcIjEyMzQ1Njc4OVwiICAgICAgICAgICAgICAgICAgLy8gQ2xvdWQgTWVzc2FnaW5nXG4gKiAgIH0sXG4gKiAgIHtcbiAqICAgIGF1dGhJZFRva2VuOiBcIllvdXIgQXV0aCBJRCBUb2tlblwiXG4gKiAgIH0pO1xuICogYGBgXG4gKlxuICogQHBhcmFtIG9wdGlvbnMgLSBgRmlyZWJhc2UuQXBwT3B0aW9uc2AgdG8gY29uZmlndXJlIHRoZSBhcHAncyBzZXJ2aWNlcywgb3IgYVxuICogICBhIGBGaXJlYmFzZUFwcGAgaW5zdGFuY2Ugd2hpY2ggY29udGFpbnMgdGhlIGBBcHBPcHRpb25zYCB3aXRoaW4uXG4gKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgYEZpcmViYXNlU2VydmVyQXBwYCBzZXR0aW5ncy5cbiAqXG4gKiBAcmV0dXJucyBUaGUgaW5pdGlhbGl6ZWQgYEZpcmViYXNlU2VydmVyQXBwYC5cbiAqXG4gKiBAdGhyb3dzIElmIGludm9rZWQgaW4gYW4gdW5zdXBwb3J0ZWQgbm9uLXNlcnZlciBlbnZpcm9ubWVudCBzdWNoIGFzIGEgYnJvd3Nlci5cbiAqXG4gKiBAdGhyb3dzIElmIHtAbGluayBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzLnJlbGVhc2VPbkRlcmVmfSBpcyBkZWZpbmVkIGJ1dCB0aGUgcnVudGltZSBkb2Vzbid0XG4gKiAgIHByb3ZpZGUgRmluYWxpemF0aW9uIFJlZ2lzdHJ5IHN1cHBvcnQuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVNlcnZlckFwcChcbiAgb3B0aW9uczogRmlyZWJhc2VPcHRpb25zIHwgRmlyZWJhc2VBcHAsXG4gIGNvbmZpZz86IEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3Ncbik6IEZpcmViYXNlU2VydmVyQXBwO1xuXG4vKipcbiAqIENyZWF0ZXMgYW5kIGluaXRpYWxpemVzIGEge0BsaW5rIEBmaXJlYmFzZS9hcHAjRmlyZWJhc2VTZXJ2ZXJBcHB9IGluc3RhbmNlLlxuICpcbiAqIEBwYXJhbSBjb25maWcgLSBPcHRpb25hbCBgRmlyZWJhc2VTZXJ2ZXJBcHBgIHNldHRpbmdzLlxuICpcbiAqIEByZXR1cm5zIFRoZSBpbml0aWFsaXplZCBgRmlyZWJhc2VTZXJ2ZXJBcHBgLlxuICpcbiAqIEB0aHJvd3MgSWYgaW52b2tlZCBpbiBhbiB1bnN1cHBvcnRlZCBub24tc2VydmVyIGVudmlyb25tZW50IHN1Y2ggYXMgYSBicm93c2VyLlxuICogQHRocm93cyBJZiB7QGxpbmsgRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncy5yZWxlYXNlT25EZXJlZn0gaXMgZGVmaW5lZCBidXQgdGhlIHJ1bnRpbWUgZG9lc24ndFxuICogICBwcm92aWRlIEZpbmFsaXphdGlvbiBSZWdpc3RyeSBzdXBwb3J0LlxuICogQHRocm93cyBJZiB0aGUgYEZJUkVCQVNFX09QVElPTlNgIGVudmlyb25tZW50IHZhcmlhYmxlIGRvZXMgbm90IGNvbnRhaW4gYSB2YWxpZCBwcm9qZWN0XG4gKiAgIGNvbmZpZ3VyYXRpb24gcmVxdWlyZWQgZm9yIGF1dG8taW5pdGlhbGl6YXRpb24uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVNlcnZlckFwcChcbiAgY29uZmlnPzogRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5nc1xuKTogRmlyZWJhc2VTZXJ2ZXJBcHA7XG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZVNlcnZlckFwcChcbiAgX29wdGlvbnM/OiBGaXJlYmFzZUFwcCB8IEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MgfCBGaXJlYmFzZU9wdGlvbnMsXG4gIF9zZXJ2ZXJBcHBDb25maWc6IEZpcmViYXNlU2VydmVyQXBwU2V0dGluZ3MgPSB7fVxuKTogRmlyZWJhc2VTZXJ2ZXJBcHAge1xuICBpZiAoaXNCcm93c2VyKCkgJiYgIWlzV2ViV29ya2VyKCkpIHtcbiAgICAvLyBGaXJlYmFzZVNlcnZlckFwcCBpc24ndCBkZXNpZ25lZCB0byBiZSBydW4gaW4gYnJvd3NlcnMuXG4gICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuSU5WQUxJRF9TRVJWRVJfQVBQX0VOVklST05NRU5UKTtcbiAgfVxuXG4gIGxldCBmaXJlYmFzZU9wdGlvbnM6IEZpcmViYXNlT3B0aW9ucyB8IHVuZGVmaW5lZDtcbiAgbGV0IHNlcnZlckFwcFNldHRpbmdzOiBGaXJlYmFzZVNlcnZlckFwcFNldHRpbmdzID0gX3NlcnZlckFwcENvbmZpZyB8fCB7fTtcblxuICBpZiAoX29wdGlvbnMpIHtcbiAgICBpZiAoX2lzRmlyZWJhc2VBcHAoX29wdGlvbnMpKSB7XG4gICAgICBmaXJlYmFzZU9wdGlvbnMgPSBfb3B0aW9ucy5vcHRpb25zO1xuICAgIH0gZWxzZSBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHBTZXR0aW5ncyhfb3B0aW9ucykpIHtcbiAgICAgIHNlcnZlckFwcFNldHRpbmdzID0gX29wdGlvbnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZpcmViYXNlT3B0aW9ucyA9IF9vcHRpb25zO1xuICAgIH1cbiAgfVxuXG4gIGlmIChzZXJ2ZXJBcHBTZXR0aW5ncy5hdXRvbWF0aWNEYXRhQ29sbGVjdGlvbkVuYWJsZWQgPT09IHVuZGVmaW5lZCkge1xuICAgIHNlcnZlckFwcFNldHRpbmdzLmF1dG9tYXRpY0RhdGFDb2xsZWN0aW9uRW5hYmxlZCA9IHRydWU7XG4gIH1cblxuICBmaXJlYmFzZU9wdGlvbnMgfHw9IGdldERlZmF1bHRBcHBDb25maWcoKTtcbiAgaWYgKCFmaXJlYmFzZU9wdGlvbnMpIHtcbiAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5OT19PUFRJT05TKTtcbiAgfVxuXG4gIC8vIEJ1aWxkIGFuIGFwcCBuYW1lIGJhc2VkIG9uIGEgaGFzaCBvZiB0aGUgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICBjb25zdCBuYW1lT2JqID0ge1xuICAgIC4uLnNlcnZlckFwcFNldHRpbmdzLFxuICAgIC4uLmZpcmViYXNlT3B0aW9uc1xuICB9O1xuXG4gIC8vIEhvd2V2ZXIsIERvIG5vdCBtYW5nbGUgdGhlIG5hbWUgYmFzZWQgb24gcmVsZWFzZU9uRGVyZWYsIHNpbmNlIGl0IHdpbGwgdmFyeSBiZXR3ZWVuIHRoZVxuICAvLyBjb25zdHJ1Y3Rpb24gb2YgRmlyZWJhc2VTZXJ2ZXJBcHAgaW5zdGFuY2VzLiBGb3IgZXhhbXBsZSwgaWYgdGhlIG9iamVjdCBpcyB0aGUgcmVxdWVzdCBoZWFkZXJzLlxuICBpZiAobmFtZU9iai5yZWxlYXNlT25EZXJlZiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgZGVsZXRlIG5hbWVPYmoucmVsZWFzZU9uRGVyZWY7XG4gIH1cblxuICBjb25zdCBoYXNoQ29kZSA9IChzOiBzdHJpbmcpOiBudW1iZXIgPT4ge1xuICAgIHJldHVybiBbLi4uc10ucmVkdWNlKFxuICAgICAgKGhhc2gsIGMpID0+IChNYXRoLmltdWwoMzEsIGhhc2gpICsgYy5jaGFyQ29kZUF0KDApKSB8IDAsXG4gICAgICAwXG4gICAgKTtcbiAgfTtcblxuICBpZiAoc2VydmVyQXBwU2V0dGluZ3MucmVsZWFzZU9uRGVyZWYgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2YgRmluYWxpemF0aW9uUmVnaXN0cnkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShcbiAgICAgICAgQXBwRXJyb3IuRklOQUxJWkFUSU9OX1JFR0lTVFJZX05PVF9TVVBQT1JURUQsXG4gICAgICAgIHt9XG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG5hbWVTdHJpbmcgPSAnJyArIGhhc2hDb2RlKEpTT04uc3RyaW5naWZ5KG5hbWVPYmopKTtcbiAgY29uc3QgZXhpc3RpbmdBcHAgPSBfc2VydmVyQXBwcy5nZXQobmFtZVN0cmluZykgYXMgRmlyZWJhc2VTZXJ2ZXJBcHA7XG4gIGlmIChleGlzdGluZ0FwcCkge1xuICAgIChleGlzdGluZ0FwcCBhcyBGaXJlYmFzZVNlcnZlckFwcEltcGwpLmluY1JlZkNvdW50KFxuICAgICAgc2VydmVyQXBwU2V0dGluZ3MucmVsZWFzZU9uRGVyZWZcbiAgICApO1xuICAgIHJldHVybiBleGlzdGluZ0FwcDtcbiAgfVxuXG4gIGNvbnN0IGNvbnRhaW5lciA9IG5ldyBDb21wb25lbnRDb250YWluZXIobmFtZVN0cmluZyk7XG4gIGZvciAoY29uc3QgY29tcG9uZW50IG9mIF9jb21wb25lbnRzLnZhbHVlcygpKSB7XG4gICAgY29udGFpbmVyLmFkZENvbXBvbmVudChjb21wb25lbnQpO1xuICB9XG5cbiAgY29uc3QgbmV3QXBwID0gbmV3IEZpcmViYXNlU2VydmVyQXBwSW1wbChcbiAgICBmaXJlYmFzZU9wdGlvbnMsXG4gICAgc2VydmVyQXBwU2V0dGluZ3MsXG4gICAgbmFtZVN0cmluZyxcbiAgICBjb250YWluZXJcbiAgKTtcblxuICBfc2VydmVyQXBwcy5zZXQobmFtZVN0cmluZywgbmV3QXBwKTtcblxuICByZXR1cm4gbmV3QXBwO1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyBhIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlQXBwfSBpbnN0YW5jZS5cbiAqXG4gKiBXaGVuIGNhbGxlZCB3aXRoIG5vIGFyZ3VtZW50cywgdGhlIGRlZmF1bHQgYXBwIGlzIHJldHVybmVkLiBXaGVuIGFuIGFwcCBuYW1lXG4gKiBpcyBwcm92aWRlZCwgdGhlIGFwcCBjb3JyZXNwb25kaW5nIHRvIHRoYXQgbmFtZSBpcyByZXR1cm5lZC5cbiAqXG4gKiBBbiBleGNlcHRpb24gaXMgdGhyb3duIGlmIHRoZSBhcHAgYmVpbmcgcmV0cmlldmVkIGhhcyBub3QgeWV0IGJlZW5cbiAqIGluaXRpYWxpemVkLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBSZXR1cm4gdGhlIGRlZmF1bHQgYXBwXG4gKiBjb25zdCBhcHAgPSBnZXRBcHAoKTtcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBSZXR1cm4gYSBuYW1lZCBhcHBcbiAqIGNvbnN0IG90aGVyQXBwID0gZ2V0QXBwKFwib3RoZXJBcHBcIik7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gbmFtZSAtIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGFwcCB0byByZXR1cm4uIElmIG5vIG5hbWUgaXNcbiAqICAgcHJvdmlkZWQsIHRoZSBkZWZhdWx0IGlzIGBcIltERUZBVUxUXVwiYC5cbiAqXG4gKiBAcmV0dXJucyBUaGUgYXBwIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3ZpZGVkIGFwcCBuYW1lLlxuICogICBJZiBubyBhcHAgbmFtZSBpcyBwcm92aWRlZCwgdGhlIGRlZmF1bHQgYXBwIGlzIHJldHVybmVkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFwcChuYW1lOiBzdHJpbmcgPSBERUZBVUxUX0VOVFJZX05BTUUpOiBGaXJlYmFzZUFwcCB7XG4gIGNvbnN0IGFwcCA9IF9hcHBzLmdldChuYW1lKTtcbiAgaWYgKCFhcHAgJiYgbmFtZSA9PT0gREVGQVVMVF9FTlRSWV9OQU1FICYmIGdldERlZmF1bHRBcHBDb25maWcoKSkge1xuICAgIHJldHVybiBpbml0aWFsaXplQXBwKCk7XG4gIH1cbiAgaWYgKCFhcHApIHtcbiAgICB0aHJvdyBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5OT19BUFAsIHsgYXBwTmFtZTogbmFtZSB9KTtcbiAgfVxuXG4gIHJldHVybiBhcHA7XG59XG5cbi8qKlxuICogQSAocmVhZC1vbmx5KSBhcnJheSBvZiBhbGwgaW5pdGlhbGl6ZWQgYXBwcy5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFwcHMoKTogRmlyZWJhc2VBcHBbXSB7XG4gIHJldHVybiBBcnJheS5mcm9tKF9hcHBzLnZhbHVlcygpKTtcbn1cblxuLyoqXG4gKiBSZW5kZXJzIHRoaXMgYXBwIHVudXNhYmxlIGFuZCBmcmVlcyB0aGUgcmVzb3VyY2VzIG9mIGFsbCBhc3NvY2lhdGVkXG4gKiBzZXJ2aWNlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogZGVsZXRlQXBwKGFwcClcbiAqICAgLnRoZW4oZnVuY3Rpb24oKSB7XG4gKiAgICAgY29uc29sZS5sb2coXCJBcHAgZGVsZXRlZCBzdWNjZXNzZnVsbHlcIik7XG4gKiAgIH0pXG4gKiAgIC5jYXRjaChmdW5jdGlvbihlcnJvcikge1xuICogICAgIGNvbnNvbGUubG9nKFwiRXJyb3IgZGVsZXRpbmcgYXBwOlwiLCBlcnJvcik7XG4gKiAgIH0pO1xuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlQXBwKGFwcDogRmlyZWJhc2VBcHApOiBQcm9taXNlPHZvaWQ+IHtcbiAgbGV0IGNsZWFudXBQcm92aWRlcnMgPSBmYWxzZTtcbiAgY29uc3QgbmFtZSA9IGFwcC5uYW1lO1xuICBpZiAoX2FwcHMuaGFzKG5hbWUpKSB7XG4gICAgY2xlYW51cFByb3ZpZGVycyA9IHRydWU7XG4gICAgX2FwcHMuZGVsZXRlKG5hbWUpO1xuICB9IGVsc2UgaWYgKF9zZXJ2ZXJBcHBzLmhhcyhuYW1lKSkge1xuICAgIGNvbnN0IGZpcmViYXNlU2VydmVyQXBwID0gYXBwIGFzIEZpcmViYXNlU2VydmVyQXBwSW1wbDtcbiAgICBpZiAoZmlyZWJhc2VTZXJ2ZXJBcHAuZGVjUmVmQ291bnQoKSA8PSAwKSB7XG4gICAgICBfc2VydmVyQXBwcy5kZWxldGUobmFtZSk7XG4gICAgICBjbGVhbnVwUHJvdmlkZXJzID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoY2xlYW51cFByb3ZpZGVycykge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgKGFwcCBhcyBGaXJlYmFzZUFwcEltcGwpLmNvbnRhaW5lclxuICAgICAgICAuZ2V0UHJvdmlkZXJzKClcbiAgICAgICAgLm1hcChwcm92aWRlciA9PiBwcm92aWRlci5kZWxldGUoKSlcbiAgICApO1xuICAgIChhcHAgYXMgRmlyZWJhc2VBcHBJbXBsKS5pc0RlbGV0ZWQgPSB0cnVlO1xuICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIGEgbGlicmFyeSdzIG5hbWUgYW5kIHZlcnNpb24gZm9yIHBsYXRmb3JtIGxvZ2dpbmcgcHVycG9zZXMuXG4gKiBAcGFyYW0gbGlicmFyeSAtIE5hbWUgb2YgMXAgb3IgM3AgbGlicmFyeSAoZS5nLiBmaXJlc3RvcmUsIGFuZ3VsYXJmaXJlKVxuICogQHBhcmFtIHZlcnNpb24gLSBDdXJyZW50IHZlcnNpb24gb2YgdGhhdCBsaWJyYXJ5LlxuICogQHBhcmFtIHZhcmlhbnQgLSBCdW5kbGUgdmFyaWFudCwgZS5nLiwgbm9kZSwgcm4sIGV0Yy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlclZlcnNpb24oXG4gIGxpYnJhcnlLZXlPck5hbWU6IHN0cmluZyxcbiAgdmVyc2lvbjogc3RyaW5nLFxuICB2YXJpYW50Pzogc3RyaW5nXG4pOiB2b2lkIHtcbiAgLy8gVE9ETzogV2UgY2FuIHVzZSB0aGlzIGNoZWNrIHRvIHdoaXRlbGlzdCBzdHJpbmdzIHdoZW4vaWYgd2Ugc2V0IHVwXG4gIC8vIGEgZ29vZCB3aGl0ZWxpc3Qgc3lzdGVtLlxuICBsZXQgbGlicmFyeSA9IFBMQVRGT1JNX0xPR19TVFJJTkdbbGlicmFyeUtleU9yTmFtZV0gPz8gbGlicmFyeUtleU9yTmFtZTtcbiAgaWYgKHZhcmlhbnQpIHtcbiAgICBsaWJyYXJ5ICs9IGAtJHt2YXJpYW50fWA7XG4gIH1cbiAgY29uc3QgbGlicmFyeU1pc21hdGNoID0gbGlicmFyeS5tYXRjaCgvXFxzfFxcLy8pO1xuICBjb25zdCB2ZXJzaW9uTWlzbWF0Y2ggPSB2ZXJzaW9uLm1hdGNoKC9cXHN8XFwvLyk7XG4gIGlmIChsaWJyYXJ5TWlzbWF0Y2ggfHwgdmVyc2lvbk1pc21hdGNoKSB7XG4gICAgY29uc3Qgd2FybmluZyA9IFtcbiAgICAgIGBVbmFibGUgdG8gcmVnaXN0ZXIgbGlicmFyeSBcIiR7bGlicmFyeX1cIiB3aXRoIHZlcnNpb24gXCIke3ZlcnNpb259XCI6YFxuICAgIF07XG4gICAgaWYgKGxpYnJhcnlNaXNtYXRjaCkge1xuICAgICAgd2FybmluZy5wdXNoKFxuICAgICAgICBgbGlicmFyeSBuYW1lIFwiJHtsaWJyYXJ5fVwiIGNvbnRhaW5zIGlsbGVnYWwgY2hhcmFjdGVycyAod2hpdGVzcGFjZSBvciBcIi9cIilgXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAobGlicmFyeU1pc21hdGNoICYmIHZlcnNpb25NaXNtYXRjaCkge1xuICAgICAgd2FybmluZy5wdXNoKCdhbmQnKTtcbiAgICB9XG4gICAgaWYgKHZlcnNpb25NaXNtYXRjaCkge1xuICAgICAgd2FybmluZy5wdXNoKFxuICAgICAgICBgdmVyc2lvbiBuYW1lIFwiJHt2ZXJzaW9ufVwiIGNvbnRhaW5zIGlsbGVnYWwgY2hhcmFjdGVycyAod2hpdGVzcGFjZSBvciBcIi9cIilgXG4gICAgICApO1xuICAgIH1cbiAgICBsb2dnZXIud2Fybih3YXJuaW5nLmpvaW4oJyAnKSk7XG4gICAgcmV0dXJuO1xuICB9XG4gIF9yZWdpc3RlckNvbXBvbmVudChcbiAgICBuZXcgQ29tcG9uZW50KFxuICAgICAgYCR7bGlicmFyeX0tdmVyc2lvbmAgYXMgTmFtZSxcbiAgICAgICgpID0+ICh7IGxpYnJhcnksIHZlcnNpb24gfSksXG4gICAgICBDb21wb25lbnRUeXBlLlZFUlNJT05cbiAgICApXG4gICk7XG59XG5cbi8qKlxuICogU2V0cyBsb2cgaGFuZGxlciBmb3IgYWxsIEZpcmViYXNlIFNES3MuXG4gKiBAcGFyYW0gbG9nQ2FsbGJhY2sgLSBBbiBvcHRpb25hbCBjdXN0b20gbG9nIGhhbmRsZXIgdGhhdCBleGVjdXRlcyB1c2VyIGNvZGUgd2hlbmV2ZXJcbiAqIHRoZSBGaXJlYmFzZSBTREsgbWFrZXMgYSBsb2dnaW5nIGNhbGwuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25Mb2coXG4gIGxvZ0NhbGxiYWNrOiBMb2dDYWxsYmFjayB8IG51bGwsXG4gIG9wdGlvbnM/OiBMb2dPcHRpb25zXG4pOiB2b2lkIHtcbiAgaWYgKGxvZ0NhbGxiYWNrICE9PSBudWxsICYmIHR5cGVvZiBsb2dDYWxsYmFjayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IEVSUk9SX0ZBQ1RPUlkuY3JlYXRlKEFwcEVycm9yLklOVkFMSURfTE9HX0FSR1VNRU5UKTtcbiAgfVxuICBzZXRVc2VyTG9nSGFuZGxlcihsb2dDYWxsYmFjaywgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogU2V0cyBsb2cgbGV2ZWwgZm9yIGFsbCBGaXJlYmFzZSBTREtzLlxuICpcbiAqIEFsbCBvZiB0aGUgbG9nIHR5cGVzIGFib3ZlIHRoZSBjdXJyZW50IGxvZyBsZXZlbCBhcmUgY2FwdHVyZWQgKGkuZS4gaWZcbiAqIHlvdSBzZXQgdGhlIGxvZyBsZXZlbCB0byBgaW5mb2AsIGVycm9ycyBhcmUgbG9nZ2VkLCBidXQgYGRlYnVnYCBhbmRcbiAqIGB2ZXJib3NlYCBsb2dzIGFyZSBub3QpLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldExvZ0xldmVsKGxvZ0xldmVsOiBMb2dMZXZlbFN0cmluZyk6IHZvaWQge1xuICBzZXRMb2dMZXZlbEltcGwobG9nTGV2ZWwpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEZpcmViYXNlRXJyb3IgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBEQlNjaGVtYSwgb3BlbkRCLCBJREJQRGF0YWJhc2UgfSBmcm9tICdpZGInO1xuaW1wb3J0IHsgQXBwRXJyb3IsIEVSUk9SX0ZBQ1RPUlkgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBGaXJlYmFzZUFwcCB9IGZyb20gJy4vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IEhlYXJ0YmVhdHNJbkluZGV4ZWREQiB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXInO1xuXG5jb25zdCBEQl9OQU1FID0gJ2ZpcmViYXNlLWhlYXJ0YmVhdC1kYXRhYmFzZSc7XG5jb25zdCBEQl9WRVJTSU9OID0gMTtcbmNvbnN0IFNUT1JFX05BTUUgPSAnZmlyZWJhc2UtaGVhcnRiZWF0LXN0b3JlJztcblxuaW50ZXJmYWNlIEFwcERCIGV4dGVuZHMgREJTY2hlbWEge1xuICAnZmlyZWJhc2UtaGVhcnRiZWF0LXN0b3JlJzoge1xuICAgIGtleTogc3RyaW5nO1xuICAgIHZhbHVlOiBIZWFydGJlYXRzSW5JbmRleGVkREI7XG4gIH07XG59XG5cbmxldCBkYlByb21pc2U6IFByb21pc2U8SURCUERhdGFiYXNlPEFwcERCPj4gfCBudWxsID0gbnVsbDtcbmZ1bmN0aW9uIGdldERiUHJvbWlzZSgpOiBQcm9taXNlPElEQlBEYXRhYmFzZTxBcHBEQj4+IHtcbiAgaWYgKCFkYlByb21pc2UpIHtcbiAgICBkYlByb21pc2UgPSBvcGVuREI8QXBwREI+KERCX05BTUUsIERCX1ZFUlNJT04sIHtcbiAgICAgIHVwZ3JhZGU6IChkYiwgb2xkVmVyc2lvbikgPT4ge1xuICAgICAgICAvLyBXZSBkb24ndCB1c2UgJ2JyZWFrJyBpbiB0aGlzIHN3aXRjaCBzdGF0ZW1lbnQsIHRoZSBmYWxsLXRocm91Z2hcbiAgICAgICAgLy8gYmVoYXZpb3IgaXMgd2hhdCB3ZSB3YW50LCBiZWNhdXNlIGlmIHRoZXJlIGFyZSBtdWx0aXBsZSB2ZXJzaW9ucyBiZXR3ZWVuXG4gICAgICAgIC8vIHRoZSBvbGQgdmVyc2lvbiBhbmQgdGhlIGN1cnJlbnQgdmVyc2lvbiwgd2Ugd2FudCBBTEwgdGhlIG1pZ3JhdGlvbnNcbiAgICAgICAgLy8gdGhhdCBjb3JyZXNwb25kIHRvIHRob3NlIHZlcnNpb25zIHRvIHJ1biwgbm90IG9ubHkgdGhlIGxhc3Qgb25lLlxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVmYXVsdC1jYXNlXG4gICAgICAgIHN3aXRjaCAob2xkVmVyc2lvbikge1xuICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKFNUT1JFX05BTUUpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAvLyBTYWZhcmkvaU9TIGJyb3dzZXJzIHRocm93IG9jY2FzaW9uYWwgZXhjZXB0aW9ucyBvblxuICAgICAgICAgICAgICAvLyBkYi5jcmVhdGVPYmplY3RTdG9yZSgpIHRoYXQgbWF5IGJlIGEgYnVnLiBBdm9pZCBibG9ja2luZ1xuICAgICAgICAgICAgICAvLyB0aGUgcmVzdCBvZiB0aGUgYXBwIGZ1bmN0aW9uYWxpdHkuXG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pLmNhdGNoKGUgPT4ge1xuICAgICAgdGhyb3cgRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuSURCX09QRU4sIHtcbiAgICAgICAgb3JpZ2luYWxFcnJvck1lc3NhZ2U6IGUubWVzc2FnZVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGRiUHJvbWlzZTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRIZWFydGJlYXRzRnJvbUluZGV4ZWREQihcbiAgYXBwOiBGaXJlYmFzZUFwcFxuKTogUHJvbWlzZTxIZWFydGJlYXRzSW5JbmRleGVkREIgfCB1bmRlZmluZWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBkYiA9IGF3YWl0IGdldERiUHJvbWlzZSgpO1xuICAgIGNvbnN0IHR4ID0gZGIudHJhbnNhY3Rpb24oU1RPUkVfTkFNRSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdHgub2JqZWN0U3RvcmUoU1RPUkVfTkFNRSkuZ2V0KGNvbXB1dGVLZXkoYXBwKSk7XG4gICAgLy8gV2UgYWxyZWFkeSBoYXZlIHRoZSB2YWx1ZSBidXQgdHguZG9uZSBjYW4gdGhyb3csXG4gICAgLy8gc28gd2UgbmVlZCB0byBhd2FpdCBpdCBoZXJlIHRvIGNhdGNoIGVycm9yc1xuICAgIGF3YWl0IHR4LmRvbmU7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgRmlyZWJhc2VFcnJvcikge1xuICAgICAgbG9nZ2VyLndhcm4oZS5tZXNzYWdlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgaWRiR2V0RXJyb3IgPSBFUlJPUl9GQUNUT1JZLmNyZWF0ZShBcHBFcnJvci5JREJfR0VULCB7XG4gICAgICAgIG9yaWdpbmFsRXJyb3JNZXNzYWdlOiAoZSBhcyBFcnJvcik/Lm1lc3NhZ2VcbiAgICAgIH0pO1xuICAgICAgbG9nZ2VyLndhcm4oaWRiR2V0RXJyb3IubWVzc2FnZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZUhlYXJ0YmVhdHNUb0luZGV4ZWREQihcbiAgYXBwOiBGaXJlYmFzZUFwcCxcbiAgaGVhcnRiZWF0T2JqZWN0OiBIZWFydGJlYXRzSW5JbmRleGVkREJcbik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIGNvbnN0IGRiID0gYXdhaXQgZ2V0RGJQcm9taXNlKCk7XG4gICAgY29uc3QgdHggPSBkYi50cmFuc2FjdGlvbihTVE9SRV9OQU1FLCAncmVhZHdyaXRlJyk7XG4gICAgY29uc3Qgb2JqZWN0U3RvcmUgPSB0eC5vYmplY3RTdG9yZShTVE9SRV9OQU1FKTtcbiAgICBhd2FpdCBvYmplY3RTdG9yZS5wdXQoaGVhcnRiZWF0T2JqZWN0LCBjb21wdXRlS2V5KGFwcCkpO1xuICAgIGF3YWl0IHR4LmRvbmU7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIEZpcmViYXNlRXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKGUubWVzc2FnZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGlkYkdldEVycm9yID0gRVJST1JfRkFDVE9SWS5jcmVhdGUoQXBwRXJyb3IuSURCX1dSSVRFLCB7XG4gICAgICAgIG9yaWdpbmFsRXJyb3JNZXNzYWdlOiAoZSBhcyBFcnJvcik/Lm1lc3NhZ2VcbiAgICAgIH0pO1xuICAgICAgbG9nZ2VyLndhcm4oaWRiR2V0RXJyb3IubWVzc2FnZSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVLZXkoYXBwOiBGaXJlYmFzZUFwcCk6IHN0cmluZyB7XG4gIHJldHVybiBgJHthcHAubmFtZX0hJHthcHAub3B0aW9ucy5hcHBJZH1gO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IENvbXBvbmVudENvbnRhaW5lciB9IGZyb20gJ0BmaXJlYmFzZS9jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgYmFzZTY0dXJsRW5jb2RlV2l0aG91dFBhZGRpbmcsXG4gIGlzSW5kZXhlZERCQXZhaWxhYmxlLFxuICB2YWxpZGF0ZUluZGV4ZWREQk9wZW5hYmxlXG59IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7XG4gIHJlYWRIZWFydGJlYXRzRnJvbUluZGV4ZWREQixcbiAgd3JpdGVIZWFydGJlYXRzVG9JbmRleGVkREJcbn0gZnJvbSAnLi9pbmRleGVkZGInO1xuaW1wb3J0IHsgRmlyZWJhc2VBcHAgfSBmcm9tICcuL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQge1xuICBIZWFydGJlYXRzQnlVc2VyQWdlbnQsXG4gIEhlYXJ0YmVhdFNlcnZpY2UsXG4gIEhlYXJ0YmVhdHNJbkluZGV4ZWREQixcbiAgSGVhcnRiZWF0U3RvcmFnZSxcbiAgU2luZ2xlRGF0ZUhlYXJ0YmVhdFxufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyJztcblxuY29uc3QgTUFYX0hFQURFUl9CWVRFUyA9IDEwMjQ7XG5leHBvcnQgY29uc3QgTUFYX05VTV9TVE9SRURfSEVBUlRCRUFUUyA9IDMwO1xuXG5leHBvcnQgY2xhc3MgSGVhcnRiZWF0U2VydmljZUltcGwgaW1wbGVtZW50cyBIZWFydGJlYXRTZXJ2aWNlIHtcbiAgLyoqXG4gICAqIFRoZSBwZXJzaXN0ZW5jZSBsYXllciBmb3IgaGVhcnRiZWF0c1xuICAgKiBMZWF2ZSBwdWJsaWMgZm9yIGVhc2llciB0ZXN0aW5nLlxuICAgKi9cbiAgX3N0b3JhZ2U6IEhlYXJ0YmVhdFN0b3JhZ2VJbXBsO1xuXG4gIC8qKlxuICAgKiBJbi1tZW1vcnkgY2FjaGUgZm9yIGhlYXJ0YmVhdHMsIHVzZWQgYnkgZ2V0SGVhcnRiZWF0c0hlYWRlcigpIHRvIGdlbmVyYXRlXG4gICAqIHRoZSBoZWFkZXIgc3RyaW5nLlxuICAgKiBTdG9yZXMgb25lIHJlY29yZCBwZXIgZGF0ZS4gVGhpcyB3aWxsIGJlIGNvbnNvbGlkYXRlZCBpbnRvIHRoZSBzdGFuZGFyZFxuICAgKiBmb3JtYXQgb2Ygb25lIHJlY29yZCBwZXIgdXNlciBhZ2VudCBzdHJpbmcgYmVmb3JlIGJlaW5nIHNlbnQgYXMgYSBoZWFkZXIuXG4gICAqIFBvcHVsYXRlZCBmcm9tIGluZGV4ZWREQiB3aGVuIHRoZSBjb250cm9sbGVyIGlzIGluc3RhbnRpYXRlZCBhbmQgc2hvdWxkXG4gICAqIGJlIGtlcHQgaW4gc3luYyB3aXRoIGluZGV4ZWREQi5cbiAgICogTGVhdmUgcHVibGljIGZvciBlYXNpZXIgdGVzdGluZy5cbiAgICovXG4gIF9oZWFydGJlYXRzQ2FjaGU6IEhlYXJ0YmVhdHNJbkluZGV4ZWREQiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiB0aGUgaW5pdGlhbGl6YXRpb24gcHJvbWlzZSBmb3IgcG9wdWxhdGluZyBoZWFydGJlYXRDYWNoZS5cbiAgICogSWYgZ2V0SGVhcnRiZWF0c0hlYWRlcigpIGlzIGNhbGxlZCBiZWZvcmUgdGhlIHByb21pc2UgcmVzb2x2ZXNcbiAgICogKGhlYXJ0YmVhdHNDYWNoZSA9PSBudWxsKSwgaXQgc2hvdWxkIHdhaXQgZm9yIHRoaXMgcHJvbWlzZVxuICAgKiBMZWF2ZSBwdWJsaWMgZm9yIGVhc2llciB0ZXN0aW5nLlxuICAgKi9cbiAgX2hlYXJ0YmVhdHNDYWNoZVByb21pc2U6IFByb21pc2U8SGVhcnRiZWF0c0luSW5kZXhlZERCPjtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBjb250YWluZXI6IENvbXBvbmVudENvbnRhaW5lcikge1xuICAgIGNvbnN0IGFwcCA9IHRoaXMuY29udGFpbmVyLmdldFByb3ZpZGVyKCdhcHAnKS5nZXRJbW1lZGlhdGUoKTtcbiAgICB0aGlzLl9zdG9yYWdlID0gbmV3IEhlYXJ0YmVhdFN0b3JhZ2VJbXBsKGFwcCk7XG4gICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlUHJvbWlzZSA9IHRoaXMuX3N0b3JhZ2UucmVhZCgpLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZSA9IHJlc3VsdDtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIHRvIHJlcG9ydCBhIGhlYXJ0YmVhdC4gVGhlIGZ1bmN0aW9uIHdpbGwgZ2VuZXJhdGVcbiAgICogYSBIZWFydGJlYXRzQnlVc2VyQWdlbnQgb2JqZWN0LCB1cGRhdGUgaGVhcnRiZWF0c0NhY2hlLCBhbmQgcGVyc2lzdCBpdFxuICAgKiB0byBJbmRleGVkREIuXG4gICAqIE5vdGUgdGhhdCB3ZSBvbmx5IHN0b3JlIG9uZSBoZWFydGJlYXQgcGVyIGRheS4gU28gaWYgYSBoZWFydGJlYXQgZm9yIHRvZGF5IGlzXG4gICAqIGFscmVhZHkgbG9nZ2VkLCBzdWJzZXF1ZW50IGNhbGxzIHRvIHRoaXMgZnVuY3Rpb24gaW4gdGhlIHNhbWUgZGF5IHdpbGwgYmUgaWdub3JlZC5cbiAgICovXG4gIGFzeW5jIHRyaWdnZXJIZWFydGJlYXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBsYXRmb3JtTG9nZ2VyID0gdGhpcy5jb250YWluZXJcbiAgICAgICAgLmdldFByb3ZpZGVyKCdwbGF0Zm9ybS1sb2dnZXInKVxuICAgICAgICAuZ2V0SW1tZWRpYXRlKCk7XG5cbiAgICAgIC8vIFRoaXMgaXMgdGhlIFwiRmlyZWJhc2UgdXNlciBhZ2VudFwiIHN0cmluZyBmcm9tIHRoZSBwbGF0Zm9ybSBsb2dnZXJcbiAgICAgIC8vIHNlcnZpY2UsIG5vdCB0aGUgYnJvd3NlciB1c2VyIGFnZW50LlxuICAgICAgY29uc3QgYWdlbnQgPSBwbGF0Zm9ybUxvZ2dlci5nZXRQbGF0Zm9ybUluZm9TdHJpbmcoKTtcbiAgICAgIGNvbnN0IGRhdGUgPSBnZXRVVENEYXRlU3RyaW5nKCk7XG4gICAgICBpZiAodGhpcy5faGVhcnRiZWF0c0NhY2hlPy5oZWFydGJlYXRzID09IG51bGwpIHtcbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlID0gYXdhaXQgdGhpcy5faGVhcnRiZWF0c0NhY2hlUHJvbWlzZTtcbiAgICAgICAgLy8gSWYgd2UgZmFpbGVkIHRvIGNvbnN0cnVjdCBhIGhlYXJ0YmVhdHMgY2FjaGUsIHRoZW4gcmV0dXJuIGltbWVkaWF0ZWx5LlxuICAgICAgICBpZiAodGhpcy5faGVhcnRiZWF0c0NhY2hlPy5oZWFydGJlYXRzID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIERvIG5vdCBzdG9yZSBhIGhlYXJ0YmVhdCBpZiBvbmUgaXMgYWxyZWFkeSBzdG9yZWQgZm9yIHRoaXMgZGF5XG4gICAgICAvLyBvciBpZiBhIGhlYWRlciBoYXMgYWxyZWFkeSBiZWVuIHNlbnQgdG9kYXkuXG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5sYXN0U2VudEhlYXJ0YmVhdERhdGUgPT09IGRhdGUgfHxcbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmhlYXJ0YmVhdHMuc29tZShcbiAgICAgICAgICBzaW5nbGVEYXRlSGVhcnRiZWF0ID0+IHNpbmdsZURhdGVIZWFydGJlYXQuZGF0ZSA9PT0gZGF0ZVxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVGhlcmUgaXMgbm8gZW50cnkgZm9yIHRoaXMgZGF0ZS4gQ3JlYXRlIG9uZS5cbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmhlYXJ0YmVhdHMucHVzaCh7IGRhdGUsIGFnZW50IH0pO1xuXG4gICAgICAgIC8vIElmIHRoZSBudW1iZXIgb2Ygc3RvcmVkIGhlYXJ0YmVhdHMgZXhjZWVkcyB0aGUgbWF4aW11bSBudW1iZXIgb2Ygc3RvcmVkIGhlYXJ0YmVhdHMsIHJlbW92ZSB0aGUgaGVhcnRiZWF0IHdpdGggdGhlIGVhcmxpZXN0IGRhdGUuXG4gICAgICAgIC8vIFNpbmNlIHRoaXMgaXMgZXhlY3V0ZWQgZWFjaCB0aW1lIGEgaGVhcnRiZWF0IGlzIHB1c2hlZCwgdGhlIGxpbWl0IGNhbiBvbmx5IGJlIGV4Y2VlZGVkIGJ5IG9uZSwgc28gb25seSBvbmUgbmVlZHMgdG8gYmUgcmVtb3ZlZC5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzLmxlbmd0aCA+IE1BWF9OVU1fU1RPUkVEX0hFQVJUQkVBVFNcbiAgICAgICAgKSB7XG4gICAgICAgICAgY29uc3QgZWFybGllc3RIZWFydGJlYXRJZHggPSBnZXRFYXJsaWVzdEhlYXJ0YmVhdElkeChcbiAgICAgICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUuaGVhcnRiZWF0cy5zcGxpY2UoZWFybGllc3RIZWFydGJlYXRJZHgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9zdG9yYWdlLm92ZXJ3cml0ZSh0aGlzLl9oZWFydGJlYXRzQ2FjaGUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZ2dlci53YXJuKGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgYmFzZTY0IGVuY29kZWQgc3RyaW5nIHdoaWNoIGNhbiBiZSBhdHRhY2hlZCB0byB0aGUgaGVhcnRiZWF0LXNwZWNpZmljIGhlYWRlciBkaXJlY3RseS5cbiAgICogSXQgYWxzbyBjbGVhcnMgYWxsIGhlYXJ0YmVhdHMgZnJvbSBtZW1vcnkgYXMgd2VsbCBhcyBpbiBJbmRleGVkREIuXG4gICAqXG4gICAqIE5PVEU6IENvbnN1bWluZyBwcm9kdWN0IFNES3Mgc2hvdWxkIG5vdCBzZW5kIHRoZSBoZWFkZXIgaWYgdGhpcyBtZXRob2RcbiAgICogcmV0dXJucyBhbiBlbXB0eSBzdHJpbmcuXG4gICAqL1xuICBhc3luYyBnZXRIZWFydGJlYXRzSGVhZGVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLl9oZWFydGJlYXRzQ2FjaGUgPT09IG51bGwpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5faGVhcnRiZWF0c0NhY2hlUHJvbWlzZTtcbiAgICAgIH1cbiAgICAgIC8vIElmIGl0J3Mgc3RpbGwgbnVsbCBvciB0aGUgYXJyYXkgaXMgZW1wdHksIHRoZXJlIGlzIG5vIGRhdGEgdG8gc2VuZC5cbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlPy5oZWFydGJlYXRzID09IG51bGwgfHxcbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmhlYXJ0YmVhdHMubGVuZ3RoID09PSAwXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0ZSA9IGdldFVUQ0RhdGVTdHJpbmcoKTtcbiAgICAgIC8vIEV4dHJhY3QgYXMgbWFueSBoZWFydGJlYXRzIGZyb20gdGhlIGNhY2hlIGFzIHdpbGwgZml0IHVuZGVyIHRoZSBzaXplIGxpbWl0LlxuICAgICAgY29uc3QgeyBoZWFydGJlYXRzVG9TZW5kLCB1bnNlbnRFbnRyaWVzIH0gPSBleHRyYWN0SGVhcnRiZWF0c0ZvckhlYWRlcihcbiAgICAgICAgdGhpcy5faGVhcnRiZWF0c0NhY2hlLmhlYXJ0YmVhdHNcbiAgICAgICk7XG4gICAgICBjb25zdCBoZWFkZXJTdHJpbmcgPSBiYXNlNjR1cmxFbmNvZGVXaXRob3V0UGFkZGluZyhcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoeyB2ZXJzaW9uOiAyLCBoZWFydGJlYXRzOiBoZWFydGJlYXRzVG9TZW5kIH0pXG4gICAgICApO1xuICAgICAgLy8gU3RvcmUgbGFzdCBzZW50IGRhdGUgdG8gcHJldmVudCBhbm90aGVyIGJlaW5nIGxvZ2dlZC9zZW50IGZvciB0aGUgc2FtZSBkYXkuXG4gICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUubGFzdFNlbnRIZWFydGJlYXREYXRlID0gZGF0ZTtcbiAgICAgIGlmICh1bnNlbnRFbnRyaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgLy8gU3RvcmUgYW55IHVuc2VudCBlbnRyaWVzIGlmIHRoZXkgZXhpc3QuXG4gICAgICAgIHRoaXMuX2hlYXJ0YmVhdHNDYWNoZS5oZWFydGJlYXRzID0gdW5zZW50RW50cmllcztcbiAgICAgICAgLy8gVGhpcyBzZWVtcyBtb3JlIGxpa2VseSB0aGFuIGVtcHR5aW5nIHRoZSBhcnJheSAoYmVsb3cpIHRvIGxlYWQgdG8gc29tZSBvZGQgc3RhdGVcbiAgICAgICAgLy8gc2luY2UgdGhlIGNhY2hlIGlzbid0IGVtcHR5IGFuZCB0aGlzIHdpbGwgYmUgY2FsbGVkIGFnYWluIG9uIHRoZSBuZXh0IHJlcXVlc3QsXG4gICAgICAgIC8vIGFuZCBpcyBwcm9iYWJseSBzYWZlc3QgaWYgd2UgYXdhaXQgaXQuXG4gICAgICAgIGF3YWl0IHRoaXMuX3N0b3JhZ2Uub3ZlcndyaXRlKHRoaXMuX2hlYXJ0YmVhdHNDYWNoZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9oZWFydGJlYXRzQ2FjaGUuaGVhcnRiZWF0cyA9IFtdO1xuICAgICAgICAvLyBEbyBub3Qgd2FpdCBmb3IgdGhpcywgdG8gcmVkdWNlIGxhdGVuY3kuXG4gICAgICAgIHZvaWQgdGhpcy5fc3RvcmFnZS5vdmVyd3JpdGUodGhpcy5faGVhcnRiZWF0c0NhY2hlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoZWFkZXJTdHJpbmc7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nZ2VyLndhcm4oZSk7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldFVUQ0RhdGVTdHJpbmcoKTogc3RyaW5nIHtcbiAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuICAvLyBSZXR1cm5zIGRhdGUgZm9ybWF0ICdZWVlZLU1NLUREJ1xuICByZXR1cm4gdG9kYXkudG9JU09TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMTApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEhlYXJ0YmVhdHNGb3JIZWFkZXIoXG4gIGhlYXJ0YmVhdHNDYWNoZTogU2luZ2xlRGF0ZUhlYXJ0YmVhdFtdLFxuICBtYXhTaXplID0gTUFYX0hFQURFUl9CWVRFU1xuKToge1xuICBoZWFydGJlYXRzVG9TZW5kOiBIZWFydGJlYXRzQnlVc2VyQWdlbnRbXTtcbiAgdW5zZW50RW50cmllczogU2luZ2xlRGF0ZUhlYXJ0YmVhdFtdO1xufSB7XG4gIC8vIEhlYXJ0YmVhdHMgZ3JvdXBlZCBieSB1c2VyIGFnZW50IGluIHRoZSBzdGFuZGFyZCBmb3JtYXQgdG8gYmUgc2VudCBpblxuICAvLyB0aGUgaGVhZGVyLlxuICBjb25zdCBoZWFydGJlYXRzVG9TZW5kOiBIZWFydGJlYXRzQnlVc2VyQWdlbnRbXSA9IFtdO1xuICAvLyBTaW5nbGUgZGF0ZSBmb3JtYXQgaGVhcnRiZWF0cyB0aGF0IGFyZSBub3Qgc2VudC5cbiAgbGV0IHVuc2VudEVudHJpZXMgPSBoZWFydGJlYXRzQ2FjaGUuc2xpY2UoKTtcbiAgZm9yIChjb25zdCBzaW5nbGVEYXRlSGVhcnRiZWF0IG9mIGhlYXJ0YmVhdHNDYWNoZSkge1xuICAgIC8vIExvb2sgZm9yIGFuIGV4aXN0aW5nIGVudHJ5IHdpdGggdGhlIHNhbWUgdXNlciBhZ2VudC5cbiAgICBjb25zdCBoZWFydGJlYXRFbnRyeSA9IGhlYXJ0YmVhdHNUb1NlbmQuZmluZChcbiAgICAgIGhiID0+IGhiLmFnZW50ID09PSBzaW5nbGVEYXRlSGVhcnRiZWF0LmFnZW50XG4gICAgKTtcbiAgICBpZiAoIWhlYXJ0YmVhdEVudHJ5KSB7XG4gICAgICAvLyBJZiBubyBlbnRyeSBmb3IgdGhpcyB1c2VyIGFnZW50IGV4aXN0cywgY3JlYXRlIG9uZS5cbiAgICAgIGhlYXJ0YmVhdHNUb1NlbmQucHVzaCh7XG4gICAgICAgIGFnZW50OiBzaW5nbGVEYXRlSGVhcnRiZWF0LmFnZW50LFxuICAgICAgICBkYXRlczogW3NpbmdsZURhdGVIZWFydGJlYXQuZGF0ZV1cbiAgICAgIH0pO1xuICAgICAgaWYgKGNvdW50Qnl0ZXMoaGVhcnRiZWF0c1RvU2VuZCkgPiBtYXhTaXplKSB7XG4gICAgICAgIC8vIElmIHRoZSBoZWFkZXIgd291bGQgZXhjZWVkIG1heCBzaXplLCByZW1vdmUgdGhlIGFkZGVkIGhlYXJ0YmVhdFxuICAgICAgICAvLyBlbnRyeSBhbmQgc3RvcCBhZGRpbmcgdG8gdGhlIGhlYWRlci5cbiAgICAgICAgaGVhcnRiZWF0c1RvU2VuZC5wb3AoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGhlYXJ0YmVhdEVudHJ5LmRhdGVzLnB1c2goc2luZ2xlRGF0ZUhlYXJ0YmVhdC5kYXRlKTtcbiAgICAgIC8vIElmIHRoZSBoZWFkZXIgd291bGQgZXhjZWVkIG1heCBzaXplLCByZW1vdmUgdGhlIGFkZGVkIGRhdGVcbiAgICAgIC8vIGFuZCBzdG9wIGFkZGluZyB0byB0aGUgaGVhZGVyLlxuICAgICAgaWYgKGNvdW50Qnl0ZXMoaGVhcnRiZWF0c1RvU2VuZCkgPiBtYXhTaXplKSB7XG4gICAgICAgIGhlYXJ0YmVhdEVudHJ5LmRhdGVzLnBvcCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gUG9wIHVuc2VudCBlbnRyeSBmcm9tIHF1ZXVlLiAoU2tpcHBlZCBpZiBhZGRpbmcgdGhlIGVudHJ5IGV4Y2VlZGVkXG4gICAgLy8gcXVvdGEgYW5kIHRoZSBsb29wIGJyZWFrcyBlYXJseS4pXG4gICAgdW5zZW50RW50cmllcyA9IHVuc2VudEVudHJpZXMuc2xpY2UoMSk7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBoZWFydGJlYXRzVG9TZW5kLFxuICAgIHVuc2VudEVudHJpZXNcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIEhlYXJ0YmVhdFN0b3JhZ2VJbXBsIGltcGxlbWVudHMgSGVhcnRiZWF0U3RvcmFnZSB7XG4gIHByaXZhdGUgX2NhblVzZUluZGV4ZWREQlByb21pc2U6IFByb21pc2U8Ym9vbGVhbj47XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBhcHA6IEZpcmViYXNlQXBwKSB7XG4gICAgdGhpcy5fY2FuVXNlSW5kZXhlZERCUHJvbWlzZSA9IHRoaXMucnVuSW5kZXhlZERCRW52aXJvbm1lbnRDaGVjaygpO1xuICB9XG4gIGFzeW5jIHJ1bkluZGV4ZWREQkVudmlyb25tZW50Q2hlY2soKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCFpc0luZGV4ZWREQkF2YWlsYWJsZSgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB2YWxpZGF0ZUluZGV4ZWREQk9wZW5hYmxlKClcbiAgICAgICAgLnRoZW4oKCkgPT4gdHJ1ZSlcbiAgICAgICAgLmNhdGNoKCgpID0+IGZhbHNlKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIFJlYWQgYWxsIGhlYXJ0YmVhdHMuXG4gICAqL1xuICBhc3luYyByZWFkKCk6IFByb21pc2U8SGVhcnRiZWF0c0luSW5kZXhlZERCPiB7XG4gICAgY29uc3QgY2FuVXNlSW5kZXhlZERCID0gYXdhaXQgdGhpcy5fY2FuVXNlSW5kZXhlZERCUHJvbWlzZTtcbiAgICBpZiAoIWNhblVzZUluZGV4ZWREQikge1xuICAgICAgcmV0dXJuIHsgaGVhcnRiZWF0czogW10gfTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgaWRiSGVhcnRiZWF0T2JqZWN0ID0gYXdhaXQgcmVhZEhlYXJ0YmVhdHNGcm9tSW5kZXhlZERCKHRoaXMuYXBwKTtcbiAgICAgIGlmIChpZGJIZWFydGJlYXRPYmplY3Q/LmhlYXJ0YmVhdHMpIHtcbiAgICAgICAgcmV0dXJuIGlkYkhlYXJ0YmVhdE9iamVjdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7IGhlYXJ0YmVhdHM6IFtdIH07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIC8vIG92ZXJ3cml0ZSB0aGUgc3RvcmFnZSB3aXRoIHRoZSBwcm92aWRlZCBoZWFydGJlYXRzXG4gIGFzeW5jIG92ZXJ3cml0ZShoZWFydGJlYXRzT2JqZWN0OiBIZWFydGJlYXRzSW5JbmRleGVkREIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjYW5Vc2VJbmRleGVkREIgPSBhd2FpdCB0aGlzLl9jYW5Vc2VJbmRleGVkREJQcm9taXNlO1xuICAgIGlmICghY2FuVXNlSW5kZXhlZERCKSB7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nSGVhcnRiZWF0c09iamVjdCA9IGF3YWl0IHRoaXMucmVhZCgpO1xuICAgICAgcmV0dXJuIHdyaXRlSGVhcnRiZWF0c1RvSW5kZXhlZERCKHRoaXMuYXBwLCB7XG4gICAgICAgIGxhc3RTZW50SGVhcnRiZWF0RGF0ZTpcbiAgICAgICAgICBoZWFydGJlYXRzT2JqZWN0Lmxhc3RTZW50SGVhcnRiZWF0RGF0ZSA/P1xuICAgICAgICAgIGV4aXN0aW5nSGVhcnRiZWF0c09iamVjdC5sYXN0U2VudEhlYXJ0YmVhdERhdGUsXG4gICAgICAgIGhlYXJ0YmVhdHM6IGhlYXJ0YmVhdHNPYmplY3QuaGVhcnRiZWF0c1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIC8vIGFkZCBoZWFydGJlYXRzXG4gIGFzeW5jIGFkZChoZWFydGJlYXRzT2JqZWN0OiBIZWFydGJlYXRzSW5JbmRleGVkREIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjYW5Vc2VJbmRleGVkREIgPSBhd2FpdCB0aGlzLl9jYW5Vc2VJbmRleGVkREJQcm9taXNlO1xuICAgIGlmICghY2FuVXNlSW5kZXhlZERCKSB7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nSGVhcnRiZWF0c09iamVjdCA9IGF3YWl0IHRoaXMucmVhZCgpO1xuICAgICAgcmV0dXJuIHdyaXRlSGVhcnRiZWF0c1RvSW5kZXhlZERCKHRoaXMuYXBwLCB7XG4gICAgICAgIGxhc3RTZW50SGVhcnRiZWF0RGF0ZTpcbiAgICAgICAgICBoZWFydGJlYXRzT2JqZWN0Lmxhc3RTZW50SGVhcnRiZWF0RGF0ZSA/P1xuICAgICAgICAgIGV4aXN0aW5nSGVhcnRiZWF0c09iamVjdC5sYXN0U2VudEhlYXJ0YmVhdERhdGUsXG4gICAgICAgIGhlYXJ0YmVhdHM6IFtcbiAgICAgICAgICAuLi5leGlzdGluZ0hlYXJ0YmVhdHNPYmplY3QuaGVhcnRiZWF0cyxcbiAgICAgICAgICAuLi5oZWFydGJlYXRzT2JqZWN0LmhlYXJ0YmVhdHNcbiAgICAgICAgXVxuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIGJ5dGVzIG9mIGEgSGVhcnRiZWF0c0J5VXNlckFnZW50IGFycmF5IGFmdGVyIGJlaW5nIHdyYXBwZWRcbiAqIGluIGEgcGxhdGZvcm0gbG9nZ2luZyBoZWFkZXIgSlNPTiBvYmplY3QsIHN0cmluZ2lmaWVkLCBhbmQgY29udmVydGVkXG4gKiB0byBiYXNlIDY0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRCeXRlcyhoZWFydGJlYXRzQ2FjaGU6IEhlYXJ0YmVhdHNCeVVzZXJBZ2VudFtdKTogbnVtYmVyIHtcbiAgLy8gYmFzZTY0IGhhcyBhIHJlc3RyaWN0ZWQgc2V0IG9mIGNoYXJhY3RlcnMsIGFsbCBvZiB3aGljaCBzaG91bGQgYmUgMSBieXRlLlxuICByZXR1cm4gYmFzZTY0dXJsRW5jb2RlV2l0aG91dFBhZGRpbmcoXG4gICAgLy8gaGVhcnRiZWF0c0NhY2hlIHdyYXBwZXIgcHJvcGVydGllc1xuICAgIEpTT04uc3RyaW5naWZ5KHsgdmVyc2lvbjogMiwgaGVhcnRiZWF0czogaGVhcnRiZWF0c0NhY2hlIH0pXG4gICkubGVuZ3RoO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBoZWFydGJlYXQgd2l0aCB0aGUgZWFybGllc3QgZGF0ZS5cbiAqIElmIHRoZSBoZWFydGJlYXRzIGFycmF5IGlzIGVtcHR5LCAtMSBpcyByZXR1cm5lZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEVhcmxpZXN0SGVhcnRiZWF0SWR4KFxuICBoZWFydGJlYXRzOiBTaW5nbGVEYXRlSGVhcnRiZWF0W11cbik6IG51bWJlciB7XG4gIGlmIChoZWFydGJlYXRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIGxldCBlYXJsaWVzdEhlYXJ0YmVhdElkeCA9IDA7XG4gIGxldCBlYXJsaWVzdEhlYXJ0YmVhdERhdGUgPSBoZWFydGJlYXRzWzBdLmRhdGU7XG5cbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBoZWFydGJlYXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGhlYXJ0YmVhdHNbaV0uZGF0ZSA8IGVhcmxpZXN0SGVhcnRiZWF0RGF0ZSkge1xuICAgICAgZWFybGllc3RIZWFydGJlYXREYXRlID0gaGVhcnRiZWF0c1tpXS5kYXRlO1xuICAgICAgZWFybGllc3RIZWFydGJlYXRJZHggPSBpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBlYXJsaWVzdEhlYXJ0YmVhdElkeDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnQsIENvbXBvbmVudFR5cGUgfSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcbmltcG9ydCB7IFBsYXRmb3JtTG9nZ2VyU2VydmljZUltcGwgfSBmcm9tICcuL3BsYXRmb3JtTG9nZ2VyU2VydmljZSc7XG5pbXBvcnQgeyBuYW1lLCB2ZXJzaW9uIH0gZnJvbSAnLi4vcGFja2FnZS5qc29uJztcbmltcG9ydCB7IF9yZWdpc3RlckNvbXBvbmVudCB9IGZyb20gJy4vaW50ZXJuYWwnO1xuaW1wb3J0IHsgcmVnaXN0ZXJWZXJzaW9uIH0gZnJvbSAnLi9hcGknO1xuaW1wb3J0IHsgSGVhcnRiZWF0U2VydmljZUltcGwgfSBmcm9tICcuL2hlYXJ0YmVhdFNlcnZpY2UnO1xuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJDb3JlQ29tcG9uZW50cyh2YXJpYW50Pzogc3RyaW5nKTogdm9pZCB7XG4gIF9yZWdpc3RlckNvbXBvbmVudChcbiAgICBuZXcgQ29tcG9uZW50KFxuICAgICAgJ3BsYXRmb3JtLWxvZ2dlcicsXG4gICAgICBjb250YWluZXIgPT4gbmV3IFBsYXRmb3JtTG9nZ2VyU2VydmljZUltcGwoY29udGFpbmVyKSxcbiAgICAgIENvbXBvbmVudFR5cGUuUFJJVkFURVxuICAgIClcbiAgKTtcbiAgX3JlZ2lzdGVyQ29tcG9uZW50KFxuICAgIG5ldyBDb21wb25lbnQoXG4gICAgICAnaGVhcnRiZWF0JyxcbiAgICAgIGNvbnRhaW5lciA9PiBuZXcgSGVhcnRiZWF0U2VydmljZUltcGwoY29udGFpbmVyKSxcbiAgICAgIENvbXBvbmVudFR5cGUuUFJJVkFURVxuICAgIClcbiAgKTtcblxuICAvLyBSZWdpc3RlciBgYXBwYCBwYWNrYWdlLlxuICByZWdpc3RlclZlcnNpb24obmFtZSwgdmVyc2lvbiwgdmFyaWFudCk7XG4gIC8vIEJVSUxEX1RBUkdFVCB3aWxsIGJlIHJlcGxhY2VkIGJ5IHZhbHVlcyBsaWtlIGVzbSwgY2pzLCBldGMgZHVyaW5nIHRoZSBjb21waWxhdGlvblxuICByZWdpc3RlclZlcnNpb24obmFtZSwgdmVyc2lvbiwgJ19fQlVJTERfVEFSR0VUX18nKTtcbiAgLy8gUmVnaXN0ZXIgcGxhdGZvcm0gU0RLIGlkZW50aWZpZXIgKG5vIHZlcnNpb24pLlxuICByZWdpc3RlclZlcnNpb24oJ2ZpcmUtanMnLCAnJyk7XG59XG4iLCAiLyoqXG4gKiBGaXJlYmFzZSBBcHBcbiAqXG4gKiBAcmVtYXJrcyBUaGlzIHBhY2thZ2UgY29vcmRpbmF0ZXMgdGhlIGNvbW11bmljYXRpb24gYmV0d2VlbiB0aGUgZGlmZmVyZW50IEZpcmViYXNlIGNvbXBvbmVudHNcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5cbi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IHJlZ2lzdGVyQ29yZUNvbXBvbmVudHMgfSBmcm9tICcuL3JlZ2lzdGVyQ29yZUNvbXBvbmVudHMnO1xuXG5leHBvcnQgKiBmcm9tICcuL2FwaSc7XG5leHBvcnQgKiBmcm9tICcuL2ludGVybmFsJztcbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLXR5cGVzJztcblxucmVnaXN0ZXJDb3JlQ29tcG9uZW50cygnX19SVU5USU1FX0VOVl9fJyk7XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyoqXG4gKiBBbiBlbnVtIG9mIGZhY3RvcnMgdGhhdCBtYXkgYmUgdXNlZCBmb3IgbXVsdGlmYWN0b3IgYXV0aGVudGljYXRpb24uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgRmFjdG9ySWQgPSB7XG4gIC8qKiBQaG9uZSBhcyBzZWNvbmQgZmFjdG9yICovXG4gIFBIT05FOiAncGhvbmUnLFxuICBUT1RQOiAndG90cCdcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogRW51bWVyYXRpb24gb2Ygc3VwcG9ydGVkIHByb3ZpZGVycy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBQcm92aWRlcklkID0ge1xuICAvKiogRmFjZWJvb2sgcHJvdmlkZXIgSUQgKi9cbiAgRkFDRUJPT0s6ICdmYWNlYm9vay5jb20nLFxuICAvKiogR2l0SHViIHByb3ZpZGVyIElEICovXG4gIEdJVEhVQjogJ2dpdGh1Yi5jb20nLFxuICAvKiogR29vZ2xlIHByb3ZpZGVyIElEICovXG4gIEdPT0dMRTogJ2dvb2dsZS5jb20nLFxuICAvKiogUGFzc3dvcmQgcHJvdmlkZXIgKi9cbiAgUEFTU1dPUkQ6ICdwYXNzd29yZCcsXG4gIC8qKiBQaG9uZSBwcm92aWRlciAqL1xuICBQSE9ORTogJ3Bob25lJyxcbiAgLyoqIFR3aXR0ZXIgcHJvdmlkZXIgSUQgKi9cbiAgVFdJVFRFUjogJ3R3aXR0ZXIuY29tJ1xufSBhcyBjb25zdDtcblxuLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiBzdXBwb3J0ZWQgc2lnbi1pbiBtZXRob2RzLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IFNpZ25Jbk1ldGhvZCA9IHtcbiAgLyoqIEVtYWlsIGxpbmsgc2lnbiBpbiBtZXRob2QgKi9cbiAgRU1BSUxfTElOSzogJ2VtYWlsTGluaycsXG4gIC8qKiBFbWFpbC9wYXNzd29yZCBzaWduIGluIG1ldGhvZCAqL1xuICBFTUFJTF9QQVNTV09SRDogJ3Bhc3N3b3JkJyxcbiAgLyoqIEZhY2Vib29rIHNpZ24gaW4gbWV0aG9kICovXG4gIEZBQ0VCT09LOiAnZmFjZWJvb2suY29tJyxcbiAgLyoqIEdpdEh1YiBzaWduIGluIG1ldGhvZCAqL1xuICBHSVRIVUI6ICdnaXRodWIuY29tJyxcbiAgLyoqIEdvb2dsZSBzaWduIGluIG1ldGhvZCAqL1xuICBHT09HTEU6ICdnb29nbGUuY29tJyxcbiAgLyoqIFBob25lIHNpZ24gaW4gbWV0aG9kICovXG4gIFBIT05FOiAncGhvbmUnLFxuICAvKiogVHdpdHRlciBzaWduIGluIG1ldGhvZCAqL1xuICBUV0lUVEVSOiAndHdpdHRlci5jb20nXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIHN1cHBvcnRlZCBvcGVyYXRpb24gdHlwZXMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgT3BlcmF0aW9uVHlwZSA9IHtcbiAgLyoqIE9wZXJhdGlvbiBpbnZvbHZpbmcgbGlua2luZyBhbiBhZGRpdGlvbmFsIHByb3ZpZGVyIHRvIGFuIGFscmVhZHkgc2lnbmVkLWluIHVzZXIuICovXG4gIExJTks6ICdsaW5rJyxcbiAgLyoqIE9wZXJhdGlvbiBpbnZvbHZpbmcgdXNpbmcgYSBwcm92aWRlciB0byByZWF1dGhlbnRpY2F0ZSBhbiBhbHJlYWR5IHNpZ25lZC1pbiB1c2VyLiAqL1xuICBSRUFVVEhFTlRJQ0FURTogJ3JlYXV0aGVudGljYXRlJyxcbiAgLyoqIE9wZXJhdGlvbiBpbnZvbHZpbmcgc2lnbmluZyBpbiBhIHVzZXIuICovXG4gIFNJR05fSU46ICdzaWduSW4nXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEFuIGVudW1lcmF0aW9uIG9mIHRoZSBwb3NzaWJsZSBlbWFpbCBhY3Rpb24gdHlwZXMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgQWN0aW9uQ29kZU9wZXJhdGlvbiA9IHtcbiAgLyoqIFRoZSBlbWFpbCBsaW5rIHNpZ24taW4gYWN0aW9uLiAqL1xuICBFTUFJTF9TSUdOSU46ICdFTUFJTF9TSUdOSU4nLFxuICAvKiogVGhlIHBhc3N3b3JkIHJlc2V0IGFjdGlvbi4gKi9cbiAgUEFTU1dPUkRfUkVTRVQ6ICdQQVNTV09SRF9SRVNFVCcsXG4gIC8qKiBUaGUgZW1haWwgcmV2b2NhdGlvbiBhY3Rpb24uICovXG4gIFJFQ09WRVJfRU1BSUw6ICdSRUNPVkVSX0VNQUlMJyxcbiAgLyoqIFRoZSByZXZlcnQgc2Vjb25kIGZhY3RvciBhZGRpdGlvbiBlbWFpbCBhY3Rpb24uICovXG4gIFJFVkVSVF9TRUNPTkRfRkFDVE9SX0FERElUSU9OOiAnUkVWRVJUX1NFQ09ORF9GQUNUT1JfQURESVRJT04nLFxuICAvKiogVGhlIHJldmVydCBzZWNvbmQgZmFjdG9yIGFkZGl0aW9uIGVtYWlsIGFjdGlvbi4gKi9cbiAgVkVSSUZZX0FORF9DSEFOR0VfRU1BSUw6ICdWRVJJRllfQU5EX0NIQU5HRV9FTUFJTCcsXG4gIC8qKiBUaGUgZW1haWwgdmVyaWZpY2F0aW9uIGFjdGlvbi4gKi9cbiAgVkVSSUZZX0VNQUlMOiAnVkVSSUZZX0VNQUlMJ1xufSBhcyBjb25zdDtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JNYXAsIFVzZXIgfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgRXJyb3JGYWN0b3J5LCBFcnJvck1hcCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgSWRUb2tlbk1mYVJlc3BvbnNlIH0gZnJvbSAnLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBBcHBOYW1lIH0gZnJvbSAnLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vY3JlZGVudGlhbHMnO1xuXG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIEZpcmViYXNlIEF1dGggZXJyb3IgY29kZXMuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBlbnVtIEF1dGhFcnJvckNvZGUge1xuICBBRE1JTl9PTkxZX09QRVJBVElPTiA9ICdhZG1pbi1yZXN0cmljdGVkLW9wZXJhdGlvbicsXG4gIEFSR1VNRU5UX0VSUk9SID0gJ2FyZ3VtZW50LWVycm9yJyxcbiAgQVBQX05PVF9BVVRIT1JJWkVEID0gJ2FwcC1ub3QtYXV0aG9yaXplZCcsXG4gIEFQUF9OT1RfSU5TVEFMTEVEID0gJ2FwcC1ub3QtaW5zdGFsbGVkJyxcbiAgQ0FQVENIQV9DSEVDS19GQUlMRUQgPSAnY2FwdGNoYS1jaGVjay1mYWlsZWQnLFxuICBDT0RFX0VYUElSRUQgPSAnY29kZS1leHBpcmVkJyxcbiAgQ09SRE9WQV9OT1RfUkVBRFkgPSAnY29yZG92YS1ub3QtcmVhZHknLFxuICBDT1JTX1VOU1VQUE9SVEVEID0gJ2NvcnMtdW5zdXBwb3J0ZWQnLFxuICBDUkVERU5USUFMX0FMUkVBRFlfSU5fVVNFID0gJ2NyZWRlbnRpYWwtYWxyZWFkeS1pbi11c2UnLFxuICBDUkVERU5USUFMX01JU01BVENIID0gJ2N1c3RvbS10b2tlbi1taXNtYXRjaCcsXG4gIENSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTiA9ICdyZXF1aXJlcy1yZWNlbnQtbG9naW4nLFxuICBERVBFTkRFTlRfU0RLX0lOSVRfQkVGT1JFX0FVVEggPSAnZGVwZW5kZW50LXNkay1pbml0aWFsaXplZC1iZWZvcmUtYXV0aCcsXG4gIERZTkFNSUNfTElOS19OT1RfQUNUSVZBVEVEID0gJ2R5bmFtaWMtbGluay1ub3QtYWN0aXZhdGVkJyxcbiAgRU1BSUxfQ0hBTkdFX05FRURTX1ZFUklGSUNBVElPTiA9ICdlbWFpbC1jaGFuZ2UtbmVlZHMtdmVyaWZpY2F0aW9uJyxcbiAgRU1BSUxfRVhJU1RTID0gJ2VtYWlsLWFscmVhZHktaW4tdXNlJyxcbiAgRU1VTEFUT1JfQ09ORklHX0ZBSUxFRCA9ICdlbXVsYXRvci1jb25maWctZmFpbGVkJyxcbiAgRVhQSVJFRF9PT0JfQ09ERSA9ICdleHBpcmVkLWFjdGlvbi1jb2RlJyxcbiAgRVhQSVJFRF9QT1BVUF9SRVFVRVNUID0gJ2NhbmNlbGxlZC1wb3B1cC1yZXF1ZXN0JyxcbiAgSU5URVJOQUxfRVJST1IgPSAnaW50ZXJuYWwtZXJyb3InLFxuICBJTlZBTElEX0FQSV9LRVkgPSAnaW52YWxpZC1hcGkta2V5JyxcbiAgSU5WQUxJRF9BUFBfQ1JFREVOVElBTCA9ICdpbnZhbGlkLWFwcC1jcmVkZW50aWFsJyxcbiAgSU5WQUxJRF9BUFBfSUQgPSAnaW52YWxpZC1hcHAtaWQnLFxuICBJTlZBTElEX0FVVEggPSAnaW52YWxpZC11c2VyLXRva2VuJyxcbiAgSU5WQUxJRF9BVVRIX0VWRU5UID0gJ2ludmFsaWQtYXV0aC1ldmVudCcsXG4gIElOVkFMSURfQ0VSVF9IQVNIID0gJ2ludmFsaWQtY2VydC1oYXNoJyxcbiAgSU5WQUxJRF9DT0RFID0gJ2ludmFsaWQtdmVyaWZpY2F0aW9uLWNvZGUnLFxuICBJTlZBTElEX0NPTlRJTlVFX1VSSSA9ICdpbnZhbGlkLWNvbnRpbnVlLXVyaScsXG4gIElOVkFMSURfQ09SRE9WQV9DT05GSUdVUkFUSU9OID0gJ2ludmFsaWQtY29yZG92YS1jb25maWd1cmF0aW9uJyxcbiAgSU5WQUxJRF9DVVNUT01fVE9LRU4gPSAnaW52YWxpZC1jdXN0b20tdG9rZW4nLFxuICBJTlZBTElEX0RZTkFNSUNfTElOS19ET01BSU4gPSAnaW52YWxpZC1keW5hbWljLWxpbmstZG9tYWluJyxcbiAgSU5WQUxJRF9FTUFJTCA9ICdpbnZhbGlkLWVtYWlsJyxcbiAgSU5WQUxJRF9FTVVMQVRPUl9TQ0hFTUUgPSAnaW52YWxpZC1lbXVsYXRvci1zY2hlbWUnLFxuICBJTlZBTElEX0NSRURFTlRJQUwgPSAnaW52YWxpZC1jcmVkZW50aWFsJyxcbiAgSU5WQUxJRF9NRVNTQUdFX1BBWUxPQUQgPSAnaW52YWxpZC1tZXNzYWdlLXBheWxvYWQnLFxuICBJTlZBTElEX01GQV9TRVNTSU9OID0gJ2ludmFsaWQtbXVsdGktZmFjdG9yLXNlc3Npb24nLFxuICBJTlZBTElEX09BVVRIX0NMSUVOVF9JRCA9ICdpbnZhbGlkLW9hdXRoLWNsaWVudC1pZCcsXG4gIElOVkFMSURfT0FVVEhfUFJPVklERVIgPSAnaW52YWxpZC1vYXV0aC1wcm92aWRlcicsXG4gIElOVkFMSURfT09CX0NPREUgPSAnaW52YWxpZC1hY3Rpb24tY29kZScsXG4gIElOVkFMSURfT1JJR0lOID0gJ3VuYXV0aG9yaXplZC1kb21haW4nLFxuICBJTlZBTElEX1BBU1NXT1JEID0gJ3dyb25nLXBhc3N3b3JkJyxcbiAgSU5WQUxJRF9QRVJTSVNURU5DRSA9ICdpbnZhbGlkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBJTlZBTElEX1BIT05FX05VTUJFUiA9ICdpbnZhbGlkLXBob25lLW51bWJlcicsXG4gIElOVkFMSURfUFJPVklERVJfSUQgPSAnaW52YWxpZC1wcm92aWRlci1pZCcsXG4gIElOVkFMSURfUkVDSVBJRU5UX0VNQUlMID0gJ2ludmFsaWQtcmVjaXBpZW50LWVtYWlsJyxcbiAgSU5WQUxJRF9TRU5ERVIgPSAnaW52YWxpZC1zZW5kZXInLFxuICBJTlZBTElEX1NFU1NJT05fSU5GTyA9ICdpbnZhbGlkLXZlcmlmaWNhdGlvbi1pZCcsXG4gIElOVkFMSURfVEVOQU5UX0lEID0gJ2ludmFsaWQtdGVuYW50LWlkJyxcbiAgTE9HSU5fQkxPQ0tFRCA9ICdsb2dpbi1ibG9ja2VkJyxcbiAgTUZBX0lORk9fTk9UX0ZPVU5EID0gJ211bHRpLWZhY3Rvci1pbmZvLW5vdC1mb3VuZCcsXG4gIE1GQV9SRVFVSVJFRCA9ICdtdWx0aS1mYWN0b3ItYXV0aC1yZXF1aXJlZCcsXG4gIE1JU1NJTkdfQU5EUk9JRF9QQUNLQUdFX05BTUUgPSAnbWlzc2luZy1hbmRyb2lkLXBrZy1uYW1lJyxcbiAgTUlTU0lOR19BUFBfQ1JFREVOVElBTCA9ICdtaXNzaW5nLWFwcC1jcmVkZW50aWFsJyxcbiAgTUlTU0lOR19BVVRIX0RPTUFJTiA9ICdhdXRoLWRvbWFpbi1jb25maWctcmVxdWlyZWQnLFxuICBNSVNTSU5HX0NPREUgPSAnbWlzc2luZy12ZXJpZmljYXRpb24tY29kZScsXG4gIE1JU1NJTkdfQ09OVElOVUVfVVJJID0gJ21pc3NpbmctY29udGludWUtdXJpJyxcbiAgTUlTU0lOR19JRlJBTUVfU1RBUlQgPSAnbWlzc2luZy1pZnJhbWUtc3RhcnQnLFxuICBNSVNTSU5HX0lPU19CVU5ETEVfSUQgPSAnbWlzc2luZy1pb3MtYnVuZGxlLWlkJyxcbiAgTUlTU0lOR19PUl9JTlZBTElEX05PTkNFID0gJ21pc3Npbmctb3ItaW52YWxpZC1ub25jZScsXG4gIE1JU1NJTkdfTUZBX0lORk8gPSAnbWlzc2luZy1tdWx0aS1mYWN0b3ItaW5mbycsXG4gIE1JU1NJTkdfTUZBX1NFU1NJT04gPSAnbWlzc2luZy1tdWx0aS1mYWN0b3Itc2Vzc2lvbicsXG4gIE1JU1NJTkdfUEhPTkVfTlVNQkVSID0gJ21pc3NpbmctcGhvbmUtbnVtYmVyJyxcbiAgTUlTU0lOR19QQVNTV09SRCA9ICdtaXNzaW5nLXBhc3N3b3JkJyxcbiAgTUlTU0lOR19TRVNTSU9OX0lORk8gPSAnbWlzc2luZy12ZXJpZmljYXRpb24taWQnLFxuICBNT0RVTEVfREVTVFJPWUVEID0gJ2FwcC1kZWxldGVkJyxcbiAgTkVFRF9DT05GSVJNQVRJT04gPSAnYWNjb3VudC1leGlzdHMtd2l0aC1kaWZmZXJlbnQtY3JlZGVudGlhbCcsXG4gIE5FVFdPUktfUkVRVUVTVF9GQUlMRUQgPSAnbmV0d29yay1yZXF1ZXN0LWZhaWxlZCcsXG4gIE5VTExfVVNFUiA9ICdudWxsLXVzZXInLFxuICBOT19BVVRIX0VWRU5UID0gJ25vLWF1dGgtZXZlbnQnLFxuICBOT19TVUNIX1BST1ZJREVSID0gJ25vLXN1Y2gtcHJvdmlkZXInLFxuICBPUEVSQVRJT05fTk9UX0FMTE9XRUQgPSAnb3BlcmF0aW9uLW5vdC1hbGxvd2VkJyxcbiAgT1BFUkFUSU9OX05PVF9TVVBQT1JURUQgPSAnb3BlcmF0aW9uLW5vdC1zdXBwb3J0ZWQtaW4tdGhpcy1lbnZpcm9ubWVudCcsXG4gIFBPUFVQX0JMT0NLRUQgPSAncG9wdXAtYmxvY2tlZCcsXG4gIFBPUFVQX0NMT1NFRF9CWV9VU0VSID0gJ3BvcHVwLWNsb3NlZC1ieS11c2VyJyxcbiAgUFJPVklERVJfQUxSRUFEWV9MSU5LRUQgPSAncHJvdmlkZXItYWxyZWFkeS1saW5rZWQnLFxuICBRVU9UQV9FWENFRURFRCA9ICdxdW90YS1leGNlZWRlZCcsXG4gIFJFRElSRUNUX0NBTkNFTExFRF9CWV9VU0VSID0gJ3JlZGlyZWN0LWNhbmNlbGxlZC1ieS11c2VyJyxcbiAgUkVESVJFQ1RfT1BFUkFUSU9OX1BFTkRJTkcgPSAncmVkaXJlY3Qtb3BlcmF0aW9uLXBlbmRpbmcnLFxuICBSRUpFQ1RFRF9DUkVERU5USUFMID0gJ3JlamVjdGVkLWNyZWRlbnRpYWwnLFxuICBTRUNPTkRfRkFDVE9SX0FMUkVBRFlfRU5ST0xMRUQgPSAnc2Vjb25kLWZhY3Rvci1hbHJlYWR5LWluLXVzZScsXG4gIFNFQ09ORF9GQUNUT1JfTElNSVRfRVhDRUVERUQgPSAnbWF4aW11bS1zZWNvbmQtZmFjdG9yLWNvdW50LWV4Y2VlZGVkJyxcbiAgVEVOQU5UX0lEX01JU01BVENIID0gJ3RlbmFudC1pZC1taXNtYXRjaCcsXG4gIFRJTUVPVVQgPSAndGltZW91dCcsXG4gIFRPS0VOX0VYUElSRUQgPSAndXNlci10b2tlbi1leHBpcmVkJyxcbiAgVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSID0gJ3Rvby1tYW55LXJlcXVlc3RzJyxcbiAgVU5BVVRIT1JJWkVEX0RPTUFJTiA9ICd1bmF1dGhvcml6ZWQtY29udGludWUtdXJpJyxcbiAgVU5TVVBQT1JURURfRklSU1RfRkFDVE9SID0gJ3Vuc3VwcG9ydGVkLWZpcnN0LWZhY3RvcicsXG4gIFVOU1VQUE9SVEVEX1BFUlNJU1RFTkNFID0gJ3Vuc3VwcG9ydGVkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBVTlNVUFBPUlRFRF9URU5BTlRfT1BFUkFUSU9OID0gJ3Vuc3VwcG9ydGVkLXRlbmFudC1vcGVyYXRpb24nLFxuICBVTlZFUklGSUVEX0VNQUlMID0gJ3VudmVyaWZpZWQtZW1haWwnLFxuICBVU0VSX0NBTkNFTExFRCA9ICd1c2VyLWNhbmNlbGxlZCcsXG4gIFVTRVJfREVMRVRFRCA9ICd1c2VyLW5vdC1mb3VuZCcsXG4gIFVTRVJfRElTQUJMRUQgPSAndXNlci1kaXNhYmxlZCcsXG4gIFVTRVJfTUlTTUFUQ0ggPSAndXNlci1taXNtYXRjaCcsXG4gIFVTRVJfU0lHTkVEX09VVCA9ICd1c2VyLXNpZ25lZC1vdXQnLFxuICBXRUFLX1BBU1NXT1JEID0gJ3dlYWstcGFzc3dvcmQnLFxuICBXRUJfU1RPUkFHRV9VTlNVUFBPUlRFRCA9ICd3ZWItc3RvcmFnZS11bnN1cHBvcnRlZCcsXG4gIEFMUkVBRFlfSU5JVElBTElaRUQgPSAnYWxyZWFkeS1pbml0aWFsaXplZCcsXG4gIFJFQ0FQVENIQV9OT1RfRU5BQkxFRCA9ICdyZWNhcHRjaGEtbm90LWVuYWJsZWQnLFxuICBNSVNTSU5HX1JFQ0FQVENIQV9UT0tFTiA9ICdtaXNzaW5nLXJlY2FwdGNoYS10b2tlbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX1RPS0VOID0gJ2ludmFsaWQtcmVjYXB0Y2hhLXRva2VuJyxcbiAgSU5WQUxJRF9SRUNBUFRDSEFfQUNUSU9OID0gJ2ludmFsaWQtcmVjYXB0Y2hhLWFjdGlvbicsXG4gIE1JU1NJTkdfQ0xJRU5UX1RZUEUgPSAnbWlzc2luZy1jbGllbnQtdHlwZScsXG4gIE1JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT04gPSAnbWlzc2luZy1yZWNhcHRjaGEtdmVyc2lvbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX1ZFUlNJT04gPSAnaW52YWxpZC1yZWNhcHRjaGEtdmVyc2lvbicsXG4gIElOVkFMSURfUkVRX1RZUEUgPSAnaW52YWxpZC1yZXEtdHlwZScsXG4gIFVOU1VQUE9SVEVEX1BBU1NXT1JEX1BPTElDWV9TQ0hFTUFfVkVSU0lPTiA9ICd1bnN1cHBvcnRlZC1wYXNzd29yZC1wb2xpY3ktc2NoZW1hLXZlcnNpb24nLFxuICBQQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UUyA9ICdwYXNzd29yZC1kb2VzLW5vdC1tZWV0LXJlcXVpcmVtZW50cycsXG4gIElOVkFMSURfSE9TVElOR19MSU5LX0RPTUFJTiA9ICdpbnZhbGlkLWhvc3RpbmctbGluay1kb21haW4nXG59XG5cbmZ1bmN0aW9uIF9kZWJ1Z0Vycm9yTWFwKCk6IEVycm9yTWFwPEF1dGhFcnJvckNvZGU+IHtcbiAgcmV0dXJuIHtcbiAgICBbQXV0aEVycm9yQ29kZS5BRE1JTl9PTkxZX09QRVJBVElPTl06XG4gICAgICAnVGhpcyBvcGVyYXRpb24gaXMgcmVzdHJpY3RlZCB0byBhZG1pbmlzdHJhdG9ycyBvbmx5LicsXG4gICAgW0F1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JdOiAnJyxcbiAgICBbQXV0aEVycm9yQ29kZS5BUFBfTk9UX0FVVEhPUklaRURdOlxuICAgICAgXCJUaGlzIGFwcCwgaWRlbnRpZmllZCBieSB0aGUgZG9tYWluIHdoZXJlIGl0J3MgaG9zdGVkLCBpcyBub3QgXCIgK1xuICAgICAgJ2F1dGhvcml6ZWQgdG8gdXNlIEZpcmViYXNlIEF1dGhlbnRpY2F0aW9uIHdpdGggdGhlIHByb3ZpZGVkIEFQSSBrZXkuICcgK1xuICAgICAgJ1JldmlldyB5b3VyIGtleSBjb25maWd1cmF0aW9uIGluIHRoZSBHb29nbGUgQVBJIGNvbnNvbGUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5BUFBfTk9UX0lOU1RBTExFRF06XG4gICAgICAnVGhlIHJlcXVlc3RlZCBtb2JpbGUgYXBwbGljYXRpb24gY29ycmVzcG9uZGluZyB0byB0aGUgaWRlbnRpZmllciAoJyArXG4gICAgICAnQW5kcm9pZCBwYWNrYWdlIG5hbWUgb3IgaU9TIGJ1bmRsZSBJRCkgcHJvdmlkZWQgaXMgbm90IGluc3RhbGxlZCBvbiAnICtcbiAgICAgICd0aGlzIGRldmljZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkNBUFRDSEFfQ0hFQ0tfRkFJTEVEXTpcbiAgICAgICdUaGUgcmVDQVBUQ0hBIHJlc3BvbnNlIHRva2VuIHByb3ZpZGVkIGlzIGVpdGhlciBpbnZhbGlkLCBleHBpcmVkLCAnICtcbiAgICAgICdhbHJlYWR5IHVzZWQgb3IgdGhlIGRvbWFpbiBhc3NvY2lhdGVkIHdpdGggaXQgZG9lcyBub3QgbWF0Y2ggdGhlIGxpc3QgJyArXG4gICAgICAnb2Ygd2hpdGVsaXN0ZWQgZG9tYWlucy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkNPREVfRVhQSVJFRF06XG4gICAgICAnVGhlIFNNUyBjb2RlIGhhcyBleHBpcmVkLiBQbGVhc2UgcmUtc2VuZCB0aGUgdmVyaWZpY2F0aW9uIGNvZGUgdG8gdHJ5ICcgK1xuICAgICAgJ2FnYWluLicsXG4gICAgW0F1dGhFcnJvckNvZGUuQ09SRE9WQV9OT1RfUkVBRFldOiAnQ29yZG92YSBmcmFtZXdvcmsgaXMgbm90IHJlYWR5LicsXG4gICAgW0F1dGhFcnJvckNvZGUuQ09SU19VTlNVUFBPUlRFRF06ICdUaGlzIGJyb3dzZXIgaXMgbm90IHN1cHBvcnRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkNSRURFTlRJQUxfQUxSRUFEWV9JTl9VU0VdOlxuICAgICAgJ1RoaXMgY3JlZGVudGlhbCBpcyBhbHJlYWR5IGFzc29jaWF0ZWQgd2l0aCBhIGRpZmZlcmVudCB1c2VyIGFjY291bnQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5DUkVERU5USUFMX01JU01BVENIXTpcbiAgICAgICdUaGUgY3VzdG9tIHRva2VuIGNvcnJlc3BvbmRzIHRvIGEgZGlmZmVyZW50IGF1ZGllbmNlLicsXG4gICAgW0F1dGhFcnJvckNvZGUuQ1JFREVOVElBTF9UT09fT0xEX0xPR0lOX0FHQUlOXTpcbiAgICAgICdUaGlzIG9wZXJhdGlvbiBpcyBzZW5zaXRpdmUgYW5kIHJlcXVpcmVzIHJlY2VudCBhdXRoZW50aWNhdGlvbi4gTG9nIGluICcgK1xuICAgICAgJ2FnYWluIGJlZm9yZSByZXRyeWluZyB0aGlzIHJlcXVlc3QuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5ERVBFTkRFTlRfU0RLX0lOSVRfQkVGT1JFX0FVVEhdOlxuICAgICAgJ0Fub3RoZXIgRmlyZWJhc2UgU0RLIHdhcyBpbml0aWFsaXplZCBhbmQgaXMgdHJ5aW5nIHRvIHVzZSBBdXRoIGJlZm9yZSBBdXRoIGlzICcgK1xuICAgICAgJ2luaXRpYWxpemVkLiBQbGVhc2UgYmUgc3VyZSB0byBjYWxsIGBpbml0aWFsaXplQXV0aGAgb3IgYGdldEF1dGhgIGJlZm9yZSAnICtcbiAgICAgICdzdGFydGluZyBhbnkgb3RoZXIgRmlyZWJhc2UgU0RLLicsXG4gICAgW0F1dGhFcnJvckNvZGUuRFlOQU1JQ19MSU5LX05PVF9BQ1RJVkFURURdOlxuICAgICAgJ1BsZWFzZSBhY3RpdmF0ZSBEeW5hbWljIExpbmtzIGluIHRoZSBGaXJlYmFzZSBDb25zb2xlIGFuZCBhZ3JlZSB0byB0aGUgdGVybXMgYW5kICcgK1xuICAgICAgJ2NvbmRpdGlvbnMuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5FTUFJTF9DSEFOR0VfTkVFRFNfVkVSSUZJQ0FUSU9OXTpcbiAgICAgICdNdWx0aS1mYWN0b3IgdXNlcnMgbXVzdCBhbHdheXMgaGF2ZSBhIHZlcmlmaWVkIGVtYWlsLicsXG4gICAgW0F1dGhFcnJvckNvZGUuRU1BSUxfRVhJU1RTXTpcbiAgICAgICdUaGUgZW1haWwgYWRkcmVzcyBpcyBhbHJlYWR5IGluIHVzZSBieSBhbm90aGVyIGFjY291bnQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5FTVVMQVRPUl9DT05GSUdfRkFJTEVEXTpcbiAgICAgICdBdXRoIGluc3RhbmNlIGhhcyBhbHJlYWR5IGJlZW4gdXNlZCB0byBtYWtlIGEgbmV0d29yayBjYWxsLiBBdXRoIGNhbiAnICtcbiAgICAgICdubyBsb25nZXIgYmUgY29uZmlndXJlZCB0byB1c2UgdGhlIGVtdWxhdG9yLiBUcnkgY2FsbGluZyAnICtcbiAgICAgICdcImNvbm5lY3RBdXRoRW11bGF0b3IoKVwiIHNvb25lci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLkVYUElSRURfT09CX0NPREVdOiAnVGhlIGFjdGlvbiBjb2RlIGhhcyBleHBpcmVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuRVhQSVJFRF9QT1BVUF9SRVFVRVNUXTpcbiAgICAgICdUaGlzIG9wZXJhdGlvbiBoYXMgYmVlbiBjYW5jZWxsZWQgZHVlIHRvIGFub3RoZXIgY29uZmxpY3RpbmcgcG9wdXAgYmVpbmcgb3BlbmVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JdOiAnQW4gaW50ZXJuYWwgQXV0aEVycm9yIGhhcyBvY2N1cnJlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQVBQX0NSRURFTlRJQUxdOlxuICAgICAgJ1RoZSBwaG9uZSB2ZXJpZmljYXRpb24gcmVxdWVzdCBjb250YWlucyBhbiBpbnZhbGlkIGFwcGxpY2F0aW9uIHZlcmlmaWVyLicgK1xuICAgICAgJyBUaGUgcmVDQVBUQ0hBIHRva2VuIHJlc3BvbnNlIGlzIGVpdGhlciBpbnZhbGlkIG9yIGV4cGlyZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0FQUF9JRF06XG4gICAgICAnVGhlIG1vYmlsZSBhcHAgaWRlbnRpZmllciBpcyBub3QgcmVnaXN0ZXJlZCBmb3IgdGhlIGN1cnJlbnQgcHJvamVjdC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQVVUSF06XG4gICAgICBcIlRoaXMgdXNlcidzIGNyZWRlbnRpYWwgaXNuJ3QgdmFsaWQgZm9yIHRoaXMgcHJvamVjdC4gVGhpcyBjYW4gaGFwcGVuIFwiICtcbiAgICAgIFwiaWYgdGhlIHVzZXIncyB0b2tlbiBoYXMgYmVlbiB0YW1wZXJlZCB3aXRoLCBvciBpZiB0aGUgdXNlciBpc24ndCBmb3IgXCIgK1xuICAgICAgJ3RoZSBwcm9qZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGlzIEFQSSBrZXkuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0FVVEhfRVZFTlRdOiAnQW4gaW50ZXJuYWwgQXV0aEVycm9yIGhhcyBvY2N1cnJlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09ERV06XG4gICAgICAnVGhlIFNNUyB2ZXJpZmljYXRpb24gY29kZSB1c2VkIHRvIGNyZWF0ZSB0aGUgcGhvbmUgYXV0aCBjcmVkZW50aWFsIGlzICcgK1xuICAgICAgJ2ludmFsaWQuIFBsZWFzZSByZXNlbmQgdGhlIHZlcmlmaWNhdGlvbiBjb2RlIHNtcyBhbmQgYmUgc3VyZSB0byB1c2UgdGhlICcgK1xuICAgICAgJ3ZlcmlmaWNhdGlvbiBjb2RlIHByb3ZpZGVkIGJ5IHRoZSB1c2VyLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9DT05USU5VRV9VUkldOlxuICAgICAgJ1RoZSBjb250aW51ZSBVUkwgcHJvdmlkZWQgaW4gdGhlIHJlcXVlc3QgaXMgaW52YWxpZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09SRE9WQV9DT05GSUdVUkFUSU9OXTpcbiAgICAgICdUaGUgZm9sbG93aW5nIENvcmRvdmEgcGx1Z2lucyBtdXN0IGJlIGluc3RhbGxlZCB0byBlbmFibGUgT0F1dGggc2lnbi1pbjogJyArXG4gICAgICAnY29yZG92YS1wbHVnaW4tYnVpbGRpbmZvLCBjb3Jkb3ZhLXVuaXZlcnNhbC1saW5rcy1wbHVnaW4sICcgK1xuICAgICAgJ2NvcmRvdmEtcGx1Z2luLWJyb3dzZXJ0YWIsIGNvcmRvdmEtcGx1Z2luLWluYXBwYnJvd3NlciBhbmQgJyArXG4gICAgICAnY29yZG92YS1wbHVnaW4tY3VzdG9tdXJsc2NoZW1lLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9DVVNUT01fVE9LRU5dOlxuICAgICAgJ1RoZSBjdXN0b20gdG9rZW4gZm9ybWF0IGlzIGluY29ycmVjdC4gUGxlYXNlIGNoZWNrIHRoZSBkb2N1bWVudGF0aW9uLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9EWU5BTUlDX0xJTktfRE9NQUlOXTpcbiAgICAgICdUaGUgcHJvdmlkZWQgZHluYW1pYyBsaW5rIGRvbWFpbiBpcyBub3QgY29uZmlndXJlZCBvciBhdXRob3JpemVkIGZvciB0aGUgY3VycmVudCBwcm9qZWN0LicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9FTUFJTF06ICdUaGUgZW1haWwgYWRkcmVzcyBpcyBiYWRseSBmb3JtYXR0ZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0VNVUxBVE9SX1NDSEVNRV06XG4gICAgICAnRW11bGF0b3IgVVJMIG11c3Qgc3RhcnQgd2l0aCBhIHZhbGlkIHNjaGVtZSAoaHR0cDovLyBvciBodHRwczovLykuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX0FQSV9LRVldOlxuICAgICAgJ1lvdXIgQVBJIGtleSBpcyBpbnZhbGlkLCBwbGVhc2UgY2hlY2sgeW91IGhhdmUgY29waWVkIGl0IGNvcnJlY3RseS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ0VSVF9IQVNIXTpcbiAgICAgICdUaGUgU0hBLTEgY2VydGlmaWNhdGUgaGFzaCBwcm92aWRlZCBpcyBpbnZhbGlkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9DUkVERU5USUFMXTpcbiAgICAgICdUaGUgc3VwcGxpZWQgYXV0aCBjcmVkZW50aWFsIGlzIGluY29ycmVjdCwgbWFsZm9ybWVkIG9yIGhhcyBleHBpcmVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9NRVNTQUdFX1BBWUxPQURdOlxuICAgICAgJ1RoZSBlbWFpbCB0ZW1wbGF0ZSBjb3JyZXNwb25kaW5nIHRvIHRoaXMgYWN0aW9uIGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycyBpbiBpdHMgbWVzc2FnZS4gJyArXG4gICAgICAnUGxlYXNlIGZpeCBieSBnb2luZyB0byB0aGUgQXV0aCBlbWFpbCB0ZW1wbGF0ZXMgc2VjdGlvbiBpbiB0aGUgRmlyZWJhc2UgQ29uc29sZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfTUZBX1NFU1NJT05dOlxuICAgICAgJ1RoZSByZXF1ZXN0IGRvZXMgbm90IGNvbnRhaW4gYSB2YWxpZCBwcm9vZiBvZiBmaXJzdCBmYWN0b3Igc3VjY2Vzc2Z1bCBzaWduLWluLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9PQVVUSF9QUk9WSURFUl06XG4gICAgICAnRW1haWxBdXRoUHJvdmlkZXIgaXMgbm90IHN1cHBvcnRlZCBmb3IgdGhpcyBvcGVyYXRpb24uIFRoaXMgb3BlcmF0aW9uICcgK1xuICAgICAgJ29ubHkgc3VwcG9ydHMgT0F1dGggcHJvdmlkZXJzLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9PQVVUSF9DTElFTlRfSURdOlxuICAgICAgJ1RoZSBPQXV0aCBjbGllbnQgSUQgcHJvdmlkZWQgaXMgZWl0aGVyIGludmFsaWQgb3IgZG9lcyBub3QgbWF0Y2ggdGhlICcgK1xuICAgICAgJ3NwZWNpZmllZCBBUEkga2V5LicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9PUklHSU5dOlxuICAgICAgJ1RoaXMgZG9tYWluIGlzIG5vdCBhdXRob3JpemVkIGZvciBPQXV0aCBvcGVyYXRpb25zIGZvciB5b3VyIEZpcmViYXNlICcgK1xuICAgICAgJ3Byb2plY3QuIEVkaXQgdGhlIGxpc3Qgb2YgYXV0aG9yaXplZCBkb21haW5zIGZyb20gdGhlIEZpcmViYXNlIGNvbnNvbGUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX09PQl9DT0RFXTpcbiAgICAgICdUaGUgYWN0aW9uIGNvZGUgaXMgaW52YWxpZC4gVGhpcyBjYW4gaGFwcGVuIGlmIHRoZSBjb2RlIGlzIG1hbGZvcm1lZCwgJyArXG4gICAgICAnZXhwaXJlZCwgb3IgaGFzIGFscmVhZHkgYmVlbiB1c2VkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9QQVNTV09SRF06XG4gICAgICAnVGhlIHBhc3N3b3JkIGlzIGludmFsaWQgb3IgdGhlIHVzZXIgZG9lcyBub3QgaGF2ZSBhIHBhc3N3b3JkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9QRVJTSVNURU5DRV06XG4gICAgICAnVGhlIHNwZWNpZmllZCBwZXJzaXN0ZW5jZSB0eXBlIGlzIGludmFsaWQuIEl0IGNhbiBvbmx5IGJlIGxvY2FsLCBzZXNzaW9uIG9yIG5vbmUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1BIT05FX05VTUJFUl06XG4gICAgICAnVGhlIGZvcm1hdCBvZiB0aGUgcGhvbmUgbnVtYmVyIHByb3ZpZGVkIGlzIGluY29ycmVjdC4gUGxlYXNlIGVudGVyIHRoZSAnICtcbiAgICAgICdwaG9uZSBudW1iZXIgaW4gYSBmb3JtYXQgdGhhdCBjYW4gYmUgcGFyc2VkIGludG8gRS4xNjQgZm9ybWF0LiBFLjE2NCAnICtcbiAgICAgICdwaG9uZSBudW1iZXJzIGFyZSB3cml0dGVuIGluIHRoZSBmb3JtYXQgWytdW2NvdW50cnkgY29kZV1bc3Vic2NyaWJlciAnICtcbiAgICAgICdudW1iZXIgaW5jbHVkaW5nIGFyZWEgY29kZV0uJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1BST1ZJREVSX0lEXTpcbiAgICAgICdUaGUgc3BlY2lmaWVkIHByb3ZpZGVyIElEIGlzIGludmFsaWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0lQSUVOVF9FTUFJTF06XG4gICAgICAnVGhlIGVtYWlsIGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBhY3Rpb24gZmFpbGVkIHRvIHNlbmQgYXMgdGhlIHByb3ZpZGVkICcgK1xuICAgICAgJ3JlY2lwaWVudCBlbWFpbCBhZGRyZXNzIGlzIGludmFsaWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5JTlZBTElEX1NFTkRFUl06XG4gICAgICAnVGhlIGVtYWlsIHRlbXBsYXRlIGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBhY3Rpb24gY29udGFpbnMgYW4gaW52YWxpZCBzZW5kZXIgZW1haWwgb3IgbmFtZS4gJyArXG4gICAgICAnUGxlYXNlIGZpeCBieSBnb2luZyB0byB0aGUgQXV0aCBlbWFpbCB0ZW1wbGF0ZXMgc2VjdGlvbiBpbiB0aGUgRmlyZWJhc2UgQ29uc29sZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfU0VTU0lPTl9JTkZPXTpcbiAgICAgICdUaGUgdmVyaWZpY2F0aW9uIElEIHVzZWQgdG8gY3JlYXRlIHRoZSBwaG9uZSBhdXRoIGNyZWRlbnRpYWwgaXMgaW52YWxpZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfVEVOQU5UX0lEXTpcbiAgICAgIFwiVGhlIEF1dGggaW5zdGFuY2UncyB0ZW5hbnQgSUQgaXMgaW52YWxpZC5cIixcbiAgICBbQXV0aEVycm9yQ29kZS5MT0dJTl9CTE9DS0VEXTpcbiAgICAgICdMb2dpbiBibG9ja2VkIGJ5IHVzZXItcHJvdmlkZWQgbWV0aG9kOiB7JG9yaWdpbmFsTWVzc2FnZX0nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQU5EUk9JRF9QQUNLQUdFX05BTUVdOlxuICAgICAgJ0FuIEFuZHJvaWQgUGFja2FnZSBOYW1lIG11c3QgYmUgcHJvdmlkZWQgaWYgdGhlIEFuZHJvaWQgQXBwIGlzIHJlcXVpcmVkIHRvIGJlIGluc3RhbGxlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQVVUSF9ET01BSU5dOlxuICAgICAgJ0JlIHN1cmUgdG8gaW5jbHVkZSBhdXRoRG9tYWluIHdoZW4gY2FsbGluZyBmaXJlYmFzZS5pbml0aWFsaXplQXBwKCksICcgK1xuICAgICAgJ2J5IGZvbGxvd2luZyB0aGUgaW5zdHJ1Y3Rpb25zIGluIHRoZSBGaXJlYmFzZSBjb25zb2xlLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19BUFBfQ1JFREVOVElBTF06XG4gICAgICAnVGhlIHBob25lIHZlcmlmaWNhdGlvbiByZXF1ZXN0IGlzIG1pc3NpbmcgYW4gYXBwbGljYXRpb24gdmVyaWZpZXIgJyArXG4gICAgICAnYXNzZXJ0aW9uLiBBIHJlQ0FQVENIQSByZXNwb25zZSB0b2tlbiBuZWVkcyB0byBiZSBwcm92aWRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQ09ERV06XG4gICAgICAnVGhlIHBob25lIGF1dGggY3JlZGVudGlhbCB3YXMgY3JlYXRlZCB3aXRoIGFuIGVtcHR5IFNNUyB2ZXJpZmljYXRpb24gY29kZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQ09OVElOVUVfVVJJXTpcbiAgICAgICdBIGNvbnRpbnVlIFVSTCBtdXN0IGJlIHByb3ZpZGVkIGluIHRoZSByZXF1ZXN0LicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19JRlJBTUVfU1RBUlRdOiAnQW4gaW50ZXJuYWwgQXV0aEVycm9yIGhhcyBvY2N1cnJlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfSU9TX0JVTkRMRV9JRF06XG4gICAgICAnQW4gaU9TIEJ1bmRsZSBJRCBtdXN0IGJlIHByb3ZpZGVkIGlmIGFuIEFwcCBTdG9yZSBJRCBpcyBwcm92aWRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfT1JfSU5WQUxJRF9OT05DRV06XG4gICAgICAnVGhlIHJlcXVlc3QgZG9lcyBub3QgY29udGFpbiBhIHZhbGlkIG5vbmNlLiBUaGlzIGNhbiBvY2N1ciBpZiB0aGUgJyArXG4gICAgICAnU0hBLTI1NiBoYXNoIG9mIHRoZSBwcm92aWRlZCByYXcgbm9uY2UgZG9lcyBub3QgbWF0Y2ggdGhlIGhhc2hlZCBub25jZSAnICtcbiAgICAgICdpbiB0aGUgSUQgdG9rZW4gcGF5bG9hZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfUEFTU1dPUkRdOiAnQSBub24tZW1wdHkgcGFzc3dvcmQgbXVzdCBiZSBwcm92aWRlZCcsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19NRkFfSU5GT106XG4gICAgICAnTm8gc2Vjb25kIGZhY3RvciBpZGVudGlmaWVyIGlzIHByb3ZpZGVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19NRkFfU0VTU0lPTl06XG4gICAgICAnVGhlIHJlcXVlc3QgaXMgbWlzc2luZyBwcm9vZiBvZiBmaXJzdCBmYWN0b3Igc3VjY2Vzc2Z1bCBzaWduLWluLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19QSE9ORV9OVU1CRVJdOlxuICAgICAgJ1RvIHNlbmQgdmVyaWZpY2F0aW9uIGNvZGVzLCBwcm92aWRlIGEgcGhvbmUgbnVtYmVyIGZvciB0aGUgcmVjaXBpZW50LicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUlTU0lOR19TRVNTSU9OX0lORk9dOlxuICAgICAgJ1RoZSBwaG9uZSBhdXRoIGNyZWRlbnRpYWwgd2FzIGNyZWF0ZWQgd2l0aCBhbiBlbXB0eSB2ZXJpZmljYXRpb24gSUQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5NT0RVTEVfREVTVFJPWUVEXTpcbiAgICAgICdUaGlzIGluc3RhbmNlIG9mIEZpcmViYXNlQXBwIGhhcyBiZWVuIGRlbGV0ZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5NRkFfSU5GT19OT1RfRk9VTkRdOlxuICAgICAgJ1RoZSB1c2VyIGRvZXMgbm90IGhhdmUgYSBzZWNvbmQgZmFjdG9yIG1hdGNoaW5nIHRoZSBpZGVudGlmaWVyIHByb3ZpZGVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVEXTpcbiAgICAgICdQcm9vZiBvZiBvd25lcnNoaXAgb2YgYSBzZWNvbmQgZmFjdG9yIGlzIHJlcXVpcmVkIHRvIGNvbXBsZXRlIHNpZ24taW4uJyxcbiAgICBbQXV0aEVycm9yQ29kZS5ORUVEX0NPTkZJUk1BVElPTl06XG4gICAgICAnQW4gYWNjb3VudCBhbHJlYWR5IGV4aXN0cyB3aXRoIHRoZSBzYW1lIGVtYWlsIGFkZHJlc3MgYnV0IGRpZmZlcmVudCAnICtcbiAgICAgICdzaWduLWluIGNyZWRlbnRpYWxzLiBTaWduIGluIHVzaW5nIGEgcHJvdmlkZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgJyArXG4gICAgICAnZW1haWwgYWRkcmVzcy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk5FVFdPUktfUkVRVUVTVF9GQUlMRURdOlxuICAgICAgJ0EgbmV0d29yayBBdXRoRXJyb3IgKHN1Y2ggYXMgdGltZW91dCwgaW50ZXJydXB0ZWQgY29ubmVjdGlvbiBvciB1bnJlYWNoYWJsZSBob3N0KSBoYXMgb2NjdXJyZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5OT19BVVRIX0VWRU5UXTogJ0FuIGludGVybmFsIEF1dGhFcnJvciBoYXMgb2NjdXJyZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5OT19TVUNIX1BST1ZJREVSXTpcbiAgICAgICdVc2VyIHdhcyBub3QgbGlua2VkIHRvIGFuIGFjY291bnQgd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXIuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5OVUxMX1VTRVJdOlxuICAgICAgJ0EgbnVsbCB1c2VyIG9iamVjdCB3YXMgcHJvdmlkZWQgYXMgdGhlIGFyZ3VtZW50IGZvciBhbiBvcGVyYXRpb24gd2hpY2ggJyArXG4gICAgICAncmVxdWlyZXMgYSBub24tbnVsbCB1c2VyIG9iamVjdC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk9QRVJBVElPTl9OT1RfQUxMT1dFRF06XG4gICAgICAnVGhlIGdpdmVuIHNpZ24taW4gcHJvdmlkZXIgaXMgZGlzYWJsZWQgZm9yIHRoaXMgRmlyZWJhc2UgcHJvamVjdC4gJyArXG4gICAgICAnRW5hYmxlIGl0IGluIHRoZSBGaXJlYmFzZSBjb25zb2xlLCB1bmRlciB0aGUgc2lnbi1pbiBtZXRob2QgdGFiIG9mIHRoZSAnICtcbiAgICAgICdBdXRoIHNlY3Rpb24uJyxcbiAgICBbQXV0aEVycm9yQ29kZS5PUEVSQVRJT05fTk9UX1NVUFBPUlRFRF06XG4gICAgICAnVGhpcyBvcGVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCBpbiB0aGUgZW52aXJvbm1lbnQgdGhpcyBhcHBsaWNhdGlvbiBpcyAnICtcbiAgICAgICdydW5uaW5nIG9uLiBcImxvY2F0aW9uLnByb3RvY29sXCIgbXVzdCBiZSBodHRwLCBodHRwcyBvciBjaHJvbWUtZXh0ZW5zaW9uJyArXG4gICAgICAnIGFuZCB3ZWIgc3RvcmFnZSBtdXN0IGJlIGVuYWJsZWQuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5QT1BVUF9CTE9DS0VEXTpcbiAgICAgICdVbmFibGUgdG8gZXN0YWJsaXNoIGEgY29ubmVjdGlvbiB3aXRoIHRoZSBwb3B1cC4gSXQgbWF5IGhhdmUgYmVlbiBibG9ja2VkIGJ5IHRoZSBicm93c2VyLicsXG4gICAgW0F1dGhFcnJvckNvZGUuUE9QVVBfQ0xPU0VEX0JZX1VTRVJdOlxuICAgICAgJ1RoZSBwb3B1cCBoYXMgYmVlbiBjbG9zZWQgYnkgdGhlIHVzZXIgYmVmb3JlIGZpbmFsaXppbmcgdGhlIG9wZXJhdGlvbi4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlBST1ZJREVSX0FMUkVBRFlfTElOS0VEXTpcbiAgICAgICdVc2VyIGNhbiBvbmx5IGJlIGxpbmtlZCB0byBvbmUgaWRlbnRpdHkgZm9yIHRoZSBnaXZlbiBwcm92aWRlci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVEXTpcbiAgICAgIFwiVGhlIHByb2plY3QncyBxdW90YSBmb3IgdGhpcyBvcGVyYXRpb24gaGFzIGJlZW4gZXhjZWVkZWQuXCIsXG4gICAgW0F1dGhFcnJvckNvZGUuUkVESVJFQ1RfQ0FOQ0VMTEVEX0JZX1VTRVJdOlxuICAgICAgJ1RoZSByZWRpcmVjdCBvcGVyYXRpb24gaGFzIGJlZW4gY2FuY2VsbGVkIGJ5IHRoZSB1c2VyIGJlZm9yZSBmaW5hbGl6aW5nLicsXG4gICAgW0F1dGhFcnJvckNvZGUuUkVESVJFQ1RfT1BFUkFUSU9OX1BFTkRJTkddOlxuICAgICAgJ0EgcmVkaXJlY3Qgc2lnbi1pbiBvcGVyYXRpb24gaXMgYWxyZWFkeSBwZW5kaW5nLicsXG4gICAgW0F1dGhFcnJvckNvZGUuUkVKRUNURURfQ1JFREVOVElBTF06XG4gICAgICAnVGhlIHJlcXVlc3QgY29udGFpbnMgbWFsZm9ybWVkIG9yIG1pc21hdGNoaW5nIGNyZWRlbnRpYWxzLicsXG4gICAgW0F1dGhFcnJvckNvZGUuU0VDT05EX0ZBQ1RPUl9BTFJFQURZX0VOUk9MTEVEXTpcbiAgICAgICdUaGUgc2Vjb25kIGZhY3RvciBpcyBhbHJlYWR5IGVucm9sbGVkIG9uIHRoaXMgYWNjb3VudC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlNFQ09ORF9GQUNUT1JfTElNSVRfRVhDRUVERURdOlxuICAgICAgJ1RoZSBtYXhpbXVtIGFsbG93ZWQgbnVtYmVyIG9mIHNlY29uZCBmYWN0b3JzIG9uIGEgdXNlciBoYXMgYmVlbiBleGNlZWRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlRFTkFOVF9JRF9NSVNNQVRDSF06XG4gICAgICBcIlRoZSBwcm92aWRlZCB0ZW5hbnQgSUQgZG9lcyBub3QgbWF0Y2ggdGhlIEF1dGggaW5zdGFuY2UncyB0ZW5hbnQgSURcIixcbiAgICBbQXV0aEVycm9yQ29kZS5USU1FT1VUXTogJ1RoZSBvcGVyYXRpb24gaGFzIHRpbWVkIG91dC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlRPS0VOX0VYUElSRURdOlxuICAgICAgXCJUaGUgdXNlcidzIGNyZWRlbnRpYWwgaXMgbm8gbG9uZ2VyIHZhbGlkLiBUaGUgdXNlciBtdXN0IHNpZ24gaW4gYWdhaW4uXCIsXG4gICAgW0F1dGhFcnJvckNvZGUuVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSXTpcbiAgICAgICdXZSBoYXZlIGJsb2NrZWQgYWxsIHJlcXVlc3RzIGZyb20gdGhpcyBkZXZpY2UgZHVlIHRvIHVudXN1YWwgYWN0aXZpdHkuICcgK1xuICAgICAgJ1RyeSBhZ2FpbiBsYXRlci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOQVVUSE9SSVpFRF9ET01BSU5dOlxuICAgICAgJ1RoZSBkb21haW4gb2YgdGhlIGNvbnRpbnVlIFVSTCBpcyBub3Qgd2hpdGVsaXN0ZWQuICBQbGVhc2Ugd2hpdGVsaXN0ICcgK1xuICAgICAgJ3RoZSBkb21haW4gaW4gdGhlIEZpcmViYXNlIGNvbnNvbGUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5VTlNVUFBPUlRFRF9GSVJTVF9GQUNUT1JdOlxuICAgICAgJ0Vucm9sbGluZyBhIHNlY29uZCBmYWN0b3Igb3Igc2lnbmluZyBpbiB3aXRoIGEgbXVsdGktZmFjdG9yIGFjY291bnQgcmVxdWlyZXMgc2lnbi1pbiB3aXRoIGEgc3VwcG9ydGVkIGZpcnN0IGZhY3Rvci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOU1VQUE9SVEVEX1BFUlNJU1RFTkNFXTpcbiAgICAgICdUaGUgY3VycmVudCBlbnZpcm9ubWVudCBkb2VzIG5vdCBzdXBwb3J0IHRoZSBzcGVjaWZpZWQgcGVyc2lzdGVuY2UgdHlwZS4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOU1VQUE9SVEVEX1RFTkFOVF9PUEVSQVRJT05dOlxuICAgICAgJ1RoaXMgb3BlcmF0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgaW4gYSBtdWx0aS10ZW5hbnQgY29udGV4dC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVOVkVSSUZJRURfRU1BSUxdOlxuICAgICAgJ1RoZSBvcGVyYXRpb24gcmVxdWlyZXMgYSB2ZXJpZmllZCBlbWFpbC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfQ0FOQ0VMTEVEXTpcbiAgICAgICdUaGUgdXNlciBkaWQgbm90IGdyYW50IHlvdXIgYXBwbGljYXRpb24gdGhlIHBlcm1pc3Npb25zIGl0IHJlcXVlc3RlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfREVMRVRFRF06XG4gICAgICAnVGhlcmUgaXMgbm8gdXNlciByZWNvcmQgY29ycmVzcG9uZGluZyB0byB0aGlzIGlkZW50aWZpZXIuIFRoZSB1c2VyIG1heSAnICtcbiAgICAgICdoYXZlIGJlZW4gZGVsZXRlZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfRElTQUJMRURdOlxuICAgICAgJ1RoZSB1c2VyIGFjY291bnQgaGFzIGJlZW4gZGlzYWJsZWQgYnkgYW4gYWRtaW5pc3RyYXRvci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfTUlTTUFUQ0hdOlxuICAgICAgJ1RoZSBzdXBwbGllZCBjcmVkZW50aWFscyBkbyBub3QgY29ycmVzcG9uZCB0byB0aGUgcHJldmlvdXNseSBzaWduZWQgaW4gdXNlci4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlVTRVJfU0lHTkVEX09VVF06ICcnLFxuICAgIFtBdXRoRXJyb3JDb2RlLldFQUtfUEFTU1dPUkRdOlxuICAgICAgJ1RoZSBwYXNzd29yZCBtdXN0IGJlIDYgY2hhcmFjdGVycyBsb25nIG9yIG1vcmUuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5XRUJfU1RPUkFHRV9VTlNVUFBPUlRFRF06XG4gICAgICAnVGhpcyBicm93c2VyIGlzIG5vdCBzdXBwb3J0ZWQgb3IgM3JkIHBhcnR5IGNvb2tpZXMgYW5kIGRhdGEgbWF5IGJlIGRpc2FibGVkLicsXG4gICAgW0F1dGhFcnJvckNvZGUuQUxSRUFEWV9JTklUSUFMSVpFRF06XG4gICAgICAnaW5pdGlhbGl6ZUF1dGgoKSBoYXMgYWxyZWFkeSBiZWVuIGNhbGxlZCB3aXRoICcgK1xuICAgICAgJ2RpZmZlcmVudCBvcHRpb25zLiBUbyBhdm9pZCB0aGlzIGVycm9yLCBjYWxsIGluaXRpYWxpemVBdXRoKCkgd2l0aCB0aGUgJyArXG4gICAgICAnc2FtZSBvcHRpb25zIGFzIHdoZW4gaXQgd2FzIG9yaWdpbmFsbHkgY2FsbGVkLCBvciBjYWxsIGdldEF1dGgoKSB0byByZXR1cm4gdGhlJyArXG4gICAgICAnIGFscmVhZHkgaW5pdGlhbGl6ZWQgaW5zdGFuY2UuJyxcbiAgICBbQXV0aEVycm9yQ29kZS5NSVNTSU5HX1JFQ0FQVENIQV9UT0tFTl06XG4gICAgICAnVGhlIHJlQ0FQVENIQSB0b2tlbiBpcyBtaXNzaW5nIHdoZW4gc2VuZGluZyByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9SRUNBUFRDSEFfVE9LRU5dOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgdG9rZW4gaXMgaW52YWxpZCB3aGVuIHNlbmRpbmcgcmVxdWVzdCB0byB0aGUgYmFja2VuZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfUkVDQVBUQ0hBX0FDVElPTl06XG4gICAgICAnVGhlIHJlQ0FQVENIQSBhY3Rpb24gaXMgaW52YWxpZCB3aGVuIHNlbmRpbmcgcmVxdWVzdCB0byB0aGUgYmFja2VuZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlJFQ0FQVENIQV9OT1RfRU5BQkxFRF06XG4gICAgICAncmVDQVBUQ0hBIEVudGVycHJpc2UgaW50ZWdyYXRpb24gaXMgbm90IGVuYWJsZWQgZm9yIHRoaXMgcHJvamVjdC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfQ0xJRU5UX1RZUEVdOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgY2xpZW50IHR5cGUgaXMgbWlzc2luZyB3aGVuIHNlbmRpbmcgcmVxdWVzdCB0byB0aGUgYmFja2VuZC4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT05dOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgdmVyc2lvbiBpcyBtaXNzaW5nIHdoZW4gc2VuZGluZyByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9SRVFfVFlQRV06ICdJbnZhbGlkIHJlcXVlc3QgcGFyYW1ldGVycy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfUkVDQVBUQ0hBX1ZFUlNJT05dOlxuICAgICAgJ1RoZSByZUNBUFRDSEEgdmVyc2lvbiBpcyBpbnZhbGlkIHdoZW4gc2VuZGluZyByZXF1ZXN0IHRvIHRoZSBiYWNrZW5kLicsXG4gICAgW0F1dGhFcnJvckNvZGUuVU5TVVBQT1JURURfUEFTU1dPUkRfUE9MSUNZX1NDSEVNQV9WRVJTSU9OXTpcbiAgICAgICdUaGUgcGFzc3dvcmQgcG9saWN5IHJlY2VpdmVkIGZyb20gdGhlIGJhY2tlbmQgdXNlcyBhIHNjaGVtYSB2ZXJzaW9uIHRoYXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGlzIHZlcnNpb24gb2YgdGhlIEZpcmViYXNlIFNESy4nLFxuICAgIFtBdXRoRXJyb3JDb2RlLlBBU1NXT1JEX0RPRVNfTk9UX01FRVRfUkVRVUlSRU1FTlRTXTpcbiAgICAgICdUaGUgcGFzc3dvcmQgZG9lcyBub3QgbWVldCB0aGUgcmVxdWlyZW1lbnRzLicsXG4gICAgW0F1dGhFcnJvckNvZGUuSU5WQUxJRF9IT1NUSU5HX0xJTktfRE9NQUlOXTpcbiAgICAgICdUaGUgcHJvdmlkZWQgSG9zdGluZyBsaW5rIGRvbWFpbiBpcyBub3QgY29uZmlndXJlZCBpbiBGaXJlYmFzZSBIb3N0aW5nIG9yIGlzIG5vdCBvd25lZCBieSAnICtcbiAgICAgICd0aGUgY3VycmVudCBwcm9qZWN0LiBUaGlzIGNhbm5vdCBiZSBhIGRlZmF1bHQgSG9zdGluZyBkb21haW4gKGB3ZWIuYXBwYCBvciBgZmlyZWJhc2VhcHAuY29tYCkuJ1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVycm9yTWFwUmV0cmlldmVyIGV4dGVuZHMgQXV0aEVycm9yTWFwIHtcbiAgKCk6IEVycm9yTWFwPEF1dGhFcnJvckNvZGU+O1xufVxuXG5mdW5jdGlvbiBfcHJvZEVycm9yTWFwKCk6IEVycm9yTWFwPEF1dGhFcnJvckNvZGU+IHtcbiAgLy8gV2Ugd2lsbCBpbmNsdWRlIHRoaXMgb25lIG1lc3NhZ2UgaW4gdGhlIHByb2QgZXJyb3IgbWFwIHNpbmNlIGJ5IHRoZSB2ZXJ5XG4gIC8vIG5hdHVyZSBvZiB0aGlzIGVycm9yLCBkZXZlbG9wZXJzIHdpbGwgbmV2ZXIgYmUgYWJsZSB0byBzZWUgdGhlIG1lc3NhZ2VcbiAgLy8gdXNpbmcgdGhlIGRlYnVnRXJyb3JNYXAgKHdoaWNoIGlzIGluc3RhbGxlZCBkdXJpbmcgYXV0aCBpbml0aWFsaXphdGlvbikuXG4gIHJldHVybiB7XG4gICAgW0F1dGhFcnJvckNvZGUuREVQRU5ERU5UX1NES19JTklUX0JFRk9SRV9BVVRIXTpcbiAgICAgICdBbm90aGVyIEZpcmViYXNlIFNESyB3YXMgaW5pdGlhbGl6ZWQgYW5kIGlzIHRyeWluZyB0byB1c2UgQXV0aCBiZWZvcmUgQXV0aCBpcyAnICtcbiAgICAgICdpbml0aWFsaXplZC4gUGxlYXNlIGJlIHN1cmUgdG8gY2FsbCBgaW5pdGlhbGl6ZUF1dGhgIG9yIGBnZXRBdXRoYCBiZWZvcmUgJyArXG4gICAgICAnc3RhcnRpbmcgYW55IG90aGVyIEZpcmViYXNlIFNESy4nXG4gIH0gYXMgRXJyb3JNYXA8QXV0aEVycm9yQ29kZT47XG59XG5cbi8qKlxuICogQSB2ZXJib3NlIGVycm9yIG1hcCB3aXRoIGRldGFpbGVkIGRlc2NyaXB0aW9ucyBmb3IgbW9zdCBlcnJvciBjb2Rlcy5cbiAqXG4gKiBTZWUgZGlzY3Vzc2lvbiBhdCB7QGxpbmsgQXV0aEVycm9yTWFwfVxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGRlYnVnRXJyb3JNYXA6IEF1dGhFcnJvck1hcCA9IF9kZWJ1Z0Vycm9yTWFwO1xuXG4vKipcbiAqIEEgbWluaW1hbCBlcnJvciBtYXAgd2l0aCBhbGwgdmVyYm9zZSBlcnJvciBtZXNzYWdlcyBzdHJpcHBlZC5cbiAqXG4gKiBTZWUgZGlzY3Vzc2lvbiBhdCB7QGxpbmsgQXV0aEVycm9yTWFwfVxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHByb2RFcnJvck1hcDogQXV0aEVycm9yTWFwID0gX3Byb2RFcnJvck1hcDtcblxuZXhwb3J0IGludGVyZmFjZSBOYW1lZEVycm9yUGFyYW1zIHtcbiAgYXBwTmFtZTogQXBwTmFtZTtcbiAgY3JlZGVudGlhbD86IEF1dGhDcmVkZW50aWFsO1xuICBlbWFpbD86IHN0cmluZztcbiAgcGhvbmVOdW1iZXI/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICB1c2VyPzogVXNlcjtcbiAgX3NlcnZlclJlc3BvbnNlPzogb2JqZWN0O1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG50eXBlIEdlbmVyaWNBdXRoRXJyb3JQYXJhbXMgPSB7XG4gIFtrZXkgaW4gRXhjbHVkZTxcbiAgICBBdXRoRXJyb3JDb2RlLFxuICAgIHwgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUlxuICAgIHwgQXV0aEVycm9yQ29kZS5ERVBFTkRFTlRfU0RLX0lOSVRfQkVGT1JFX0FVVEhcbiAgICB8IEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JcbiAgICB8IEF1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVEXG4gICAgfCBBdXRoRXJyb3JDb2RlLk5PX0FVVEhfRVZFTlRcbiAgICB8IEF1dGhFcnJvckNvZGUuT1BFUkFUSU9OX05PVF9TVVBQT1JURURcbiAgPl06IHtcbiAgICBhcHBOYW1lPzogQXBwTmFtZTtcbiAgICBlbWFpbD86IHN0cmluZztcbiAgICBwaG9uZU51bWJlcj86IHN0cmluZztcbiAgICBtZXNzYWdlPzogc3RyaW5nO1xuICB9O1xufTtcblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRoRXJyb3JQYXJhbXMgZXh0ZW5kcyBHZW5lcmljQXV0aEVycm9yUGFyYW1zIHtcbiAgW0F1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JdOiB7IGFwcE5hbWU/OiBBcHBOYW1lIH07XG4gIFtBdXRoRXJyb3JDb2RlLkRFUEVOREVOVF9TREtfSU5JVF9CRUZPUkVfQVVUSF06IHsgYXBwTmFtZT86IEFwcE5hbWUgfTtcbiAgW0F1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JdOiB7IGFwcE5hbWU/OiBBcHBOYW1lIH07XG4gIFtBdXRoRXJyb3JDb2RlLkxPR0lOX0JMT0NLRURdOiB7XG4gICAgYXBwTmFtZT86IEFwcE5hbWU7XG4gICAgb3JpZ2luYWxNZXNzYWdlPzogc3RyaW5nO1xuICB9O1xuICBbQXV0aEVycm9yQ29kZS5PUEVSQVRJT05fTk9UX1NVUFBPUlRFRF06IHsgYXBwTmFtZT86IEFwcE5hbWUgfTtcbiAgW0F1dGhFcnJvckNvZGUuTk9fQVVUSF9FVkVOVF06IHsgYXBwTmFtZT86IEFwcE5hbWUgfTtcbiAgW0F1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVEXToge1xuICAgIGFwcE5hbWU6IEFwcE5hbWU7XG4gICAgX3NlcnZlclJlc3BvbnNlOiBJZFRva2VuTWZhUmVzcG9uc2U7XG4gIH07XG4gIFtBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09SRE9WQV9DT05GSUdVUkFUSU9OXToge1xuICAgIGFwcE5hbWU6IEFwcE5hbWU7XG4gICAgbWlzc2luZ1BsdWdpbj86IHN0cmluZztcbiAgfTtcbn1cblxuZXhwb3J0IGNvbnN0IF9ERUZBVUxUX0FVVEhfRVJST1JfRkFDVE9SWSA9IG5ldyBFcnJvckZhY3Rvcnk8XG4gIEF1dGhFcnJvckNvZGUsXG4gIEF1dGhFcnJvclBhcmFtc1xuPignYXV0aCcsICdGaXJlYmFzZScsIF9wcm9kRXJyb3JNYXAoKSk7XG5cbi8qKlxuICogQSBtYXAgb2YgcG90ZW50aWFsIGBBdXRoYCBlcnJvciBjb2RlcywgZm9yIGVhc2llciBjb21wYXJpc29uIHdpdGggZXJyb3JzXG4gKiB0aHJvd24gYnkgdGhlIFNESy5cbiAqXG4gKiBAcmVtYXJrc1xuICogTm90ZSB0aGF0IHlvdSBjYW4ndCB0cmVlLXNoYWtlIGluZGl2aWR1YWwga2V5c1xuICogaW4gdGhlIG1hcCwgc28gYnkgdXNpbmcgdGhlIG1hcCB5b3UgbWlnaHQgc3Vic3RhbnRpYWxseSBpbmNyZWFzZSB5b3VyXG4gKiBidW5kbGUgc2l6ZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBBVVRIX0VSUk9SX0NPREVTX01BUF9ET19OT1RfVVNFX0lOVEVSTkFMTFkgPSB7XG4gIEFETUlOX09OTFlfT1BFUkFUSU9OOiAnYXV0aC9hZG1pbi1yZXN0cmljdGVkLW9wZXJhdGlvbicsXG4gIEFSR1VNRU5UX0VSUk9SOiAnYXV0aC9hcmd1bWVudC1lcnJvcicsXG4gIEFQUF9OT1RfQVVUSE9SSVpFRDogJ2F1dGgvYXBwLW5vdC1hdXRob3JpemVkJyxcbiAgQVBQX05PVF9JTlNUQUxMRUQ6ICdhdXRoL2FwcC1ub3QtaW5zdGFsbGVkJyxcbiAgQ0FQVENIQV9DSEVDS19GQUlMRUQ6ICdhdXRoL2NhcHRjaGEtY2hlY2stZmFpbGVkJyxcbiAgQ09ERV9FWFBJUkVEOiAnYXV0aC9jb2RlLWV4cGlyZWQnLFxuICBDT1JET1ZBX05PVF9SRUFEWTogJ2F1dGgvY29yZG92YS1ub3QtcmVhZHknLFxuICBDT1JTX1VOU1VQUE9SVEVEOiAnYXV0aC9jb3JzLXVuc3VwcG9ydGVkJyxcbiAgQ1JFREVOVElBTF9BTFJFQURZX0lOX1VTRTogJ2F1dGgvY3JlZGVudGlhbC1hbHJlYWR5LWluLXVzZScsXG4gIENSRURFTlRJQUxfTUlTTUFUQ0g6ICdhdXRoL2N1c3RvbS10b2tlbi1taXNtYXRjaCcsXG4gIENSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTjogJ2F1dGgvcmVxdWlyZXMtcmVjZW50LWxvZ2luJyxcbiAgREVQRU5ERU5UX1NES19JTklUX0JFRk9SRV9BVVRIOiAnYXV0aC9kZXBlbmRlbnQtc2RrLWluaXRpYWxpemVkLWJlZm9yZS1hdXRoJyxcbiAgRFlOQU1JQ19MSU5LX05PVF9BQ1RJVkFURUQ6ICdhdXRoL2R5bmFtaWMtbGluay1ub3QtYWN0aXZhdGVkJyxcbiAgRU1BSUxfQ0hBTkdFX05FRURTX1ZFUklGSUNBVElPTjogJ2F1dGgvZW1haWwtY2hhbmdlLW5lZWRzLXZlcmlmaWNhdGlvbicsXG4gIEVNQUlMX0VYSVNUUzogJ2F1dGgvZW1haWwtYWxyZWFkeS1pbi11c2UnLFxuICBFTVVMQVRPUl9DT05GSUdfRkFJTEVEOiAnYXV0aC9lbXVsYXRvci1jb25maWctZmFpbGVkJyxcbiAgRVhQSVJFRF9PT0JfQ09ERTogJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZScsXG4gIEVYUElSRURfUE9QVVBfUkVRVUVTVDogJ2F1dGgvY2FuY2VsbGVkLXBvcHVwLXJlcXVlc3QnLFxuICBJTlRFUk5BTF9FUlJPUjogJ2F1dGgvaW50ZXJuYWwtZXJyb3InLFxuICBJTlZBTElEX0FQSV9LRVk6ICdhdXRoL2ludmFsaWQtYXBpLWtleScsXG4gIElOVkFMSURfQVBQX0NSRURFTlRJQUw6ICdhdXRoL2ludmFsaWQtYXBwLWNyZWRlbnRpYWwnLFxuICBJTlZBTElEX0FQUF9JRDogJ2F1dGgvaW52YWxpZC1hcHAtaWQnLFxuICBJTlZBTElEX0FVVEg6ICdhdXRoL2ludmFsaWQtdXNlci10b2tlbicsXG4gIElOVkFMSURfQVVUSF9FVkVOVDogJ2F1dGgvaW52YWxpZC1hdXRoLWV2ZW50JyxcbiAgSU5WQUxJRF9DRVJUX0hBU0g6ICdhdXRoL2ludmFsaWQtY2VydC1oYXNoJyxcbiAgSU5WQUxJRF9DT0RFOiAnYXV0aC9pbnZhbGlkLXZlcmlmaWNhdGlvbi1jb2RlJyxcbiAgSU5WQUxJRF9DT05USU5VRV9VUkk6ICdhdXRoL2ludmFsaWQtY29udGludWUtdXJpJyxcbiAgSU5WQUxJRF9DT1JET1ZBX0NPTkZJR1VSQVRJT046ICdhdXRoL2ludmFsaWQtY29yZG92YS1jb25maWd1cmF0aW9uJyxcbiAgSU5WQUxJRF9DVVNUT01fVE9LRU46ICdhdXRoL2ludmFsaWQtY3VzdG9tLXRva2VuJyxcbiAgSU5WQUxJRF9EWU5BTUlDX0xJTktfRE9NQUlOOiAnYXV0aC9pbnZhbGlkLWR5bmFtaWMtbGluay1kb21haW4nLFxuICBJTlZBTElEX0VNQUlMOiAnYXV0aC9pbnZhbGlkLWVtYWlsJyxcbiAgSU5WQUxJRF9FTVVMQVRPUl9TQ0hFTUU6ICdhdXRoL2ludmFsaWQtZW11bGF0b3Itc2NoZW1lJyxcbiAgSU5WQUxJRF9JRFBfUkVTUE9OU0U6ICdhdXRoL2ludmFsaWQtY3JlZGVudGlhbCcsXG4gIElOVkFMSURfTE9HSU5fQ1JFREVOVElBTFM6ICdhdXRoL2ludmFsaWQtY3JlZGVudGlhbCcsXG4gIElOVkFMSURfTUVTU0FHRV9QQVlMT0FEOiAnYXV0aC9pbnZhbGlkLW1lc3NhZ2UtcGF5bG9hZCcsXG4gIElOVkFMSURfTUZBX1NFU1NJT046ICdhdXRoL2ludmFsaWQtbXVsdGktZmFjdG9yLXNlc3Npb24nLFxuICBJTlZBTElEX09BVVRIX0NMSUVOVF9JRDogJ2F1dGgvaW52YWxpZC1vYXV0aC1jbGllbnQtaWQnLFxuICBJTlZBTElEX09BVVRIX1BST1ZJREVSOiAnYXV0aC9pbnZhbGlkLW9hdXRoLXByb3ZpZGVyJyxcbiAgSU5WQUxJRF9PT0JfQ09ERTogJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZScsXG4gIElOVkFMSURfT1JJR0lOOiAnYXV0aC91bmF1dGhvcml6ZWQtZG9tYWluJyxcbiAgSU5WQUxJRF9QQVNTV09SRDogJ2F1dGgvd3JvbmctcGFzc3dvcmQnLFxuICBJTlZBTElEX1BFUlNJU1RFTkNFOiAnYXV0aC9pbnZhbGlkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBJTlZBTElEX1BIT05FX05VTUJFUjogJ2F1dGgvaW52YWxpZC1waG9uZS1udW1iZXInLFxuICBJTlZBTElEX1BST1ZJREVSX0lEOiAnYXV0aC9pbnZhbGlkLXByb3ZpZGVyLWlkJyxcbiAgSU5WQUxJRF9SRUNJUElFTlRfRU1BSUw6ICdhdXRoL2ludmFsaWQtcmVjaXBpZW50LWVtYWlsJyxcbiAgSU5WQUxJRF9TRU5ERVI6ICdhdXRoL2ludmFsaWQtc2VuZGVyJyxcbiAgSU5WQUxJRF9TRVNTSU9OX0lORk86ICdhdXRoL2ludmFsaWQtdmVyaWZpY2F0aW9uLWlkJyxcbiAgSU5WQUxJRF9URU5BTlRfSUQ6ICdhdXRoL2ludmFsaWQtdGVuYW50LWlkJyxcbiAgTUZBX0lORk9fTk9UX0ZPVU5EOiAnYXV0aC9tdWx0aS1mYWN0b3ItaW5mby1ub3QtZm91bmQnLFxuICBNRkFfUkVRVUlSRUQ6ICdhdXRoL211bHRpLWZhY3Rvci1hdXRoLXJlcXVpcmVkJyxcbiAgTUlTU0lOR19BTkRST0lEX1BBQ0tBR0VfTkFNRTogJ2F1dGgvbWlzc2luZy1hbmRyb2lkLXBrZy1uYW1lJyxcbiAgTUlTU0lOR19BUFBfQ1JFREVOVElBTDogJ2F1dGgvbWlzc2luZy1hcHAtY3JlZGVudGlhbCcsXG4gIE1JU1NJTkdfQVVUSF9ET01BSU46ICdhdXRoL2F1dGgtZG9tYWluLWNvbmZpZy1yZXF1aXJlZCcsXG4gIE1JU1NJTkdfQ09ERTogJ2F1dGgvbWlzc2luZy12ZXJpZmljYXRpb24tY29kZScsXG4gIE1JU1NJTkdfQ09OVElOVUVfVVJJOiAnYXV0aC9taXNzaW5nLWNvbnRpbnVlLXVyaScsXG4gIE1JU1NJTkdfSUZSQU1FX1NUQVJUOiAnYXV0aC9taXNzaW5nLWlmcmFtZS1zdGFydCcsXG4gIE1JU1NJTkdfSU9TX0JVTkRMRV9JRDogJ2F1dGgvbWlzc2luZy1pb3MtYnVuZGxlLWlkJyxcbiAgTUlTU0lOR19PUl9JTlZBTElEX05PTkNFOiAnYXV0aC9taXNzaW5nLW9yLWludmFsaWQtbm9uY2UnLFxuICBNSVNTSU5HX01GQV9JTkZPOiAnYXV0aC9taXNzaW5nLW11bHRpLWZhY3Rvci1pbmZvJyxcbiAgTUlTU0lOR19NRkFfU0VTU0lPTjogJ2F1dGgvbWlzc2luZy1tdWx0aS1mYWN0b3Itc2Vzc2lvbicsXG4gIE1JU1NJTkdfUEhPTkVfTlVNQkVSOiAnYXV0aC9taXNzaW5nLXBob25lLW51bWJlcicsXG4gIE1JU1NJTkdfUEFTU1dPUkQ6ICdhdXRoL21pc3NpbmctcGFzc3dvcmQnLFxuICBNSVNTSU5HX1NFU1NJT05fSU5GTzogJ2F1dGgvbWlzc2luZy12ZXJpZmljYXRpb24taWQnLFxuICBNT0RVTEVfREVTVFJPWUVEOiAnYXV0aC9hcHAtZGVsZXRlZCcsXG4gIE5FRURfQ09ORklSTUFUSU9OOiAnYXV0aC9hY2NvdW50LWV4aXN0cy13aXRoLWRpZmZlcmVudC1jcmVkZW50aWFsJyxcbiAgTkVUV09SS19SRVFVRVNUX0ZBSUxFRDogJ2F1dGgvbmV0d29yay1yZXF1ZXN0LWZhaWxlZCcsXG4gIE5VTExfVVNFUjogJ2F1dGgvbnVsbC11c2VyJyxcbiAgTk9fQVVUSF9FVkVOVDogJ2F1dGgvbm8tYXV0aC1ldmVudCcsXG4gIE5PX1NVQ0hfUFJPVklERVI6ICdhdXRoL25vLXN1Y2gtcHJvdmlkZXInLFxuICBPUEVSQVRJT05fTk9UX0FMTE9XRUQ6ICdhdXRoL29wZXJhdGlvbi1ub3QtYWxsb3dlZCcsXG4gIE9QRVJBVElPTl9OT1RfU1VQUE9SVEVEOiAnYXV0aC9vcGVyYXRpb24tbm90LXN1cHBvcnRlZC1pbi10aGlzLWVudmlyb25tZW50JyxcbiAgUE9QVVBfQkxPQ0tFRDogJ2F1dGgvcG9wdXAtYmxvY2tlZCcsXG4gIFBPUFVQX0NMT1NFRF9CWV9VU0VSOiAnYXV0aC9wb3B1cC1jbG9zZWQtYnktdXNlcicsXG4gIFBST1ZJREVSX0FMUkVBRFlfTElOS0VEOiAnYXV0aC9wcm92aWRlci1hbHJlYWR5LWxpbmtlZCcsXG4gIFFVT1RBX0VYQ0VFREVEOiAnYXV0aC9xdW90YS1leGNlZWRlZCcsXG4gIFJFRElSRUNUX0NBTkNFTExFRF9CWV9VU0VSOiAnYXV0aC9yZWRpcmVjdC1jYW5jZWxsZWQtYnktdXNlcicsXG4gIFJFRElSRUNUX09QRVJBVElPTl9QRU5ESU5HOiAnYXV0aC9yZWRpcmVjdC1vcGVyYXRpb24tcGVuZGluZycsXG4gIFJFSkVDVEVEX0NSRURFTlRJQUw6ICdhdXRoL3JlamVjdGVkLWNyZWRlbnRpYWwnLFxuICBTRUNPTkRfRkFDVE9SX0FMUkVBRFlfRU5ST0xMRUQ6ICdhdXRoL3NlY29uZC1mYWN0b3ItYWxyZWFkeS1pbi11c2UnLFxuICBTRUNPTkRfRkFDVE9SX0xJTUlUX0VYQ0VFREVEOiAnYXV0aC9tYXhpbXVtLXNlY29uZC1mYWN0b3ItY291bnQtZXhjZWVkZWQnLFxuICBURU5BTlRfSURfTUlTTUFUQ0g6ICdhdXRoL3RlbmFudC1pZC1taXNtYXRjaCcsXG4gIFRJTUVPVVQ6ICdhdXRoL3RpbWVvdXQnLFxuICBUT0tFTl9FWFBJUkVEOiAnYXV0aC91c2VyLXRva2VuLWV4cGlyZWQnLFxuICBUT09fTUFOWV9BVFRFTVBUU19UUllfTEFURVI6ICdhdXRoL3Rvby1tYW55LXJlcXVlc3RzJyxcbiAgVU5BVVRIT1JJWkVEX0RPTUFJTjogJ2F1dGgvdW5hdXRob3JpemVkLWNvbnRpbnVlLXVyaScsXG4gIFVOU1VQUE9SVEVEX0ZJUlNUX0ZBQ1RPUjogJ2F1dGgvdW5zdXBwb3J0ZWQtZmlyc3QtZmFjdG9yJyxcbiAgVU5TVVBQT1JURURfUEVSU0lTVEVOQ0U6ICdhdXRoL3Vuc3VwcG9ydGVkLXBlcnNpc3RlbmNlLXR5cGUnLFxuICBVTlNVUFBPUlRFRF9URU5BTlRfT1BFUkFUSU9OOiAnYXV0aC91bnN1cHBvcnRlZC10ZW5hbnQtb3BlcmF0aW9uJyxcbiAgVU5WRVJJRklFRF9FTUFJTDogJ2F1dGgvdW52ZXJpZmllZC1lbWFpbCcsXG4gIFVTRVJfQ0FOQ0VMTEVEOiAnYXV0aC91c2VyLWNhbmNlbGxlZCcsXG4gIFVTRVJfREVMRVRFRDogJ2F1dGgvdXNlci1ub3QtZm91bmQnLFxuICBVU0VSX0RJU0FCTEVEOiAnYXV0aC91c2VyLWRpc2FibGVkJyxcbiAgVVNFUl9NSVNNQVRDSDogJ2F1dGgvdXNlci1taXNtYXRjaCcsXG4gIFVTRVJfU0lHTkVEX09VVDogJ2F1dGgvdXNlci1zaWduZWQtb3V0JyxcbiAgV0VBS19QQVNTV09SRDogJ2F1dGgvd2Vhay1wYXNzd29yZCcsXG4gIFdFQl9TVE9SQUdFX1VOU1VQUE9SVEVEOiAnYXV0aC93ZWItc3RvcmFnZS11bnN1cHBvcnRlZCcsXG4gIEFMUkVBRFlfSU5JVElBTElaRUQ6ICdhdXRoL2FscmVhZHktaW5pdGlhbGl6ZWQnLFxuICBSRUNBUFRDSEFfTk9UX0VOQUJMRUQ6ICdhdXRoL3JlY2FwdGNoYS1ub3QtZW5hYmxlZCcsXG4gIE1JU1NJTkdfUkVDQVBUQ0hBX1RPS0VOOiAnYXV0aC9taXNzaW5nLXJlY2FwdGNoYS10b2tlbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX1RPS0VOOiAnYXV0aC9pbnZhbGlkLXJlY2FwdGNoYS10b2tlbicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX0FDVElPTjogJ2F1dGgvaW52YWxpZC1yZWNhcHRjaGEtYWN0aW9uJyxcbiAgTUlTU0lOR19DTElFTlRfVFlQRTogJ2F1dGgvbWlzc2luZy1jbGllbnQtdHlwZScsXG4gIE1JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT046ICdhdXRoL21pc3NpbmctcmVjYXB0Y2hhLXZlcnNpb24nLFxuICBJTlZBTElEX1JFQ0FQVENIQV9WRVJTSU9OOiAnYXV0aC9pbnZhbGlkLXJlY2FwdGNoYS12ZXJzaW9uJyxcbiAgSU5WQUxJRF9SRVFfVFlQRTogJ2F1dGgvaW52YWxpZC1yZXEtdHlwZScsXG4gIElOVkFMSURfSE9TVElOR19MSU5LX0RPTUFJTjogJ2F1dGgvaW52YWxpZC1ob3N0aW5nLWxpbmstZG9tYWluJ1xufSBhcyBjb25zdDtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBMb2dnZXIsIExvZ0xldmVsIH0gZnJvbSAnQGZpcmViYXNlL2xvZ2dlcic7XG5pbXBvcnQgeyBTREtfVkVSU0lPTiB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuXG5leHBvcnQgeyBMb2dMZXZlbCB9O1xuXG5jb25zdCBsb2dDbGllbnQgPSBuZXcgTG9nZ2VyKCdAZmlyZWJhc2UvYXV0aCcpO1xuXG4vLyBIZWxwZXIgbWV0aG9kcyBhcmUgbmVlZGVkIGJlY2F1c2UgdmFyaWFibGVzIGNhbid0IGJlIGV4cG9ydGVkIGFzIHJlYWQvd3JpdGVcbmV4cG9ydCBmdW5jdGlvbiBfZ2V0TG9nTGV2ZWwoKTogTG9nTGV2ZWwge1xuICByZXR1cm4gbG9nQ2xpZW50LmxvZ0xldmVsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3NldExvZ0xldmVsKG5ld0xldmVsOiBMb2dMZXZlbCk6IHZvaWQge1xuICBsb2dDbGllbnQubG9nTGV2ZWwgPSBuZXdMZXZlbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9sb2dEZWJ1Zyhtc2c6IHN0cmluZywgLi4uYXJnczogc3RyaW5nW10pOiB2b2lkIHtcbiAgaWYgKGxvZ0NsaWVudC5sb2dMZXZlbCA8PSBMb2dMZXZlbC5ERUJVRykge1xuICAgIGxvZ0NsaWVudC5kZWJ1ZyhgQXV0aCAoJHtTREtfVkVSU0lPTn0pOiAke21zZ31gLCAuLi5hcmdzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gX2xvZ1dhcm4obXNnOiBzdHJpbmcsIC4uLmFyZ3M6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGlmIChsb2dDbGllbnQubG9nTGV2ZWwgPD0gTG9nTGV2ZWwuV0FSTikge1xuICAgIGxvZ0NsaWVudC53YXJuKGBBdXRoICgke1NES19WRVJTSU9OfSk6ICR7bXNnfWAsIC4uLmFyZ3MpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfbG9nRXJyb3IobXNnOiBzdHJpbmcsIC4uLmFyZ3M6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGlmIChsb2dDbGllbnQubG9nTGV2ZWwgPD0gTG9nTGV2ZWwuRVJST1IpIHtcbiAgICBsb2dDbGllbnQuZXJyb3IoYEF1dGggKCR7U0RLX1ZFUlNJT059KTogJHttc2d9YCwgLi4uYXJncyk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEVycm9yRmFjdG9yeSwgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHtcbiAgX0RFRkFVTFRfQVVUSF9FUlJPUl9GQUNUT1JZLFxuICBBdXRoRXJyb3JDb2RlLFxuICBBdXRoRXJyb3JQYXJhbXMsXG4gIHByb2RFcnJvck1hcCxcbiAgRXJyb3JNYXBSZXRyaWV2ZXJcbn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9sb2dFcnJvciB9IGZyb20gJy4vbG9nJztcblxudHlwZSBBdXRoRXJyb3JMaXN0UGFyYW1zPEs+ID0gSyBleHRlbmRzIGtleW9mIEF1dGhFcnJvclBhcmFtc1xuICA/IFtBdXRoRXJyb3JQYXJhbXNbS11dXG4gIDogW107XG50eXBlIExlc3NBcHBOYW1lPEsgZXh0ZW5kcyBBdXRoRXJyb3JDb2RlPiA9IE9taXQ8QXV0aEVycm9yUGFyYW1zW0tdLCAnYXBwTmFtZSc+O1xuXG4vKipcbiAqIFVuY29uZGl0aW9uYWxseSBmYWlscywgdGhyb3dpbmcgYSBkZXZlbG9wZXIgZmFjaW5nIElOVEVSTkFMX0VSUk9SXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGZhaWwoYXV0aCwgQXV0aEVycm9yQ29kZS5NRkFfUkVRVUlSRUQpOyAgLy8gRXJyb3I6IHRoZSBNRkFfUkVRVUlSRUQgZXJyb3IgbmVlZHMgbW9yZSBwYXJhbXMgdGhhbiBhcHBOYW1lXG4gKiBmYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVELCB7c2VydmVyUmVzcG9uc2V9KTsgIC8vIENvbXBpbGVzXG4gKiBmYWlsKEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpOyAgLy8gQ29tcGlsZXM7IGludGVybmFsIGVycm9yIGRvZXMgbm90IG5lZWQgYXBwTmFtZVxuICogZmFpbChBdXRoRXJyb3JDb2RlLlVTRVJfREVMRVRFRCk7ICAvLyBFcnJvcjogVVNFUl9ERUxFVEVEIHJlcXVpcmVzIGFwcCBuYW1lXG4gKiBmYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuVVNFUl9ERUxFVEVEKTsgIC8vIENvbXBpbGVzOyBVU0VSX0RFTEVURUQgX29ubHlfIG5lZWRzIGFwcCBuYW1lXG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gYXBwTmFtZSBBcHAgbmFtZSBmb3IgdGFnZ2luZyB0aGUgZXJyb3JcbiAqIEB0aHJvd3MgRmlyZWJhc2VFcnJvclxuICovXG5leHBvcnQgZnVuY3Rpb24gX2ZhaWw8SyBleHRlbmRzIEF1dGhFcnJvckNvZGU+KFxuICBjb2RlOiBLLFxuICAuLi5kYXRhOiB7fSBleHRlbmRzIEF1dGhFcnJvclBhcmFtc1tLXVxuICAgID8gW0F1dGhFcnJvclBhcmFtc1tLXT9dXG4gICAgOiBbQXV0aEVycm9yUGFyYW1zW0tdXVxuKTogbmV2ZXI7XG5leHBvcnQgZnVuY3Rpb24gX2ZhaWw8SyBleHRlbmRzIEF1dGhFcnJvckNvZGU+KFxuICBhdXRoOiBBdXRoLFxuICBjb2RlOiBLLFxuICAuLi5kYXRhOiB7fSBleHRlbmRzIExlc3NBcHBOYW1lPEs+ID8gW0xlc3NBcHBOYW1lPEs+P10gOiBbTGVzc0FwcE5hbWU8Sz5dXG4pOiBuZXZlcjtcbmV4cG9ydCBmdW5jdGlvbiBfZmFpbDxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGF1dGhPckNvZGU6IEF1dGggfCBLLFxuICAuLi5yZXN0OiB1bmtub3duW11cbik6IG5ldmVyIHtcbiAgdGhyb3cgY3JlYXRlRXJyb3JJbnRlcm5hbChhdXRoT3JDb2RlLCAuLi5yZXN0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9jcmVhdGVFcnJvcjxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGNvZGU6IEssXG4gIC4uLmRhdGE6IHt9IGV4dGVuZHMgQXV0aEVycm9yUGFyYW1zW0tdXG4gICAgPyBbQXV0aEVycm9yUGFyYW1zW0tdP11cbiAgICA6IFtBdXRoRXJyb3JQYXJhbXNbS11dXG4pOiBGaXJlYmFzZUVycm9yO1xuZXhwb3J0IGZ1bmN0aW9uIF9jcmVhdGVFcnJvcjxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGF1dGg6IEF1dGgsXG4gIGNvZGU6IEssXG4gIC4uLmRhdGE6IHt9IGV4dGVuZHMgTGVzc0FwcE5hbWU8Sz4gPyBbTGVzc0FwcE5hbWU8Sz4/XSA6IFtMZXNzQXBwTmFtZTxLPl1cbik6IEZpcmViYXNlRXJyb3I7XG5leHBvcnQgZnVuY3Rpb24gX2NyZWF0ZUVycm9yPEsgZXh0ZW5kcyBBdXRoRXJyb3JDb2RlPihcbiAgYXV0aE9yQ29kZTogQXV0aCB8IEssXG4gIC4uLnJlc3Q6IHVua25vd25bXVxuKTogRmlyZWJhc2VFcnJvciB7XG4gIHJldHVybiBjcmVhdGVFcnJvckludGVybmFsKGF1dGhPckNvZGUsIC4uLnJlc3QpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2Vycm9yV2l0aEN1c3RvbU1lc3NhZ2UoXG4gIGF1dGg6IEF1dGgsXG4gIGNvZGU6IEF1dGhFcnJvckNvZGUsXG4gIG1lc3NhZ2U6IHN0cmluZ1xuKTogRmlyZWJhc2VFcnJvciB7XG4gIGNvbnN0IGVycm9yTWFwID0ge1xuICAgIC4uLihwcm9kRXJyb3JNYXAgYXMgRXJyb3JNYXBSZXRyaWV2ZXIpKCksXG4gICAgW2NvZGVdOiBtZXNzYWdlXG4gIH07XG4gIGNvbnN0IGZhY3RvcnkgPSBuZXcgRXJyb3JGYWN0b3J5PEF1dGhFcnJvckNvZGUsIEF1dGhFcnJvclBhcmFtcz4oXG4gICAgJ2F1dGgnLFxuICAgICdGaXJlYmFzZScsXG4gICAgZXJyb3JNYXBcbiAgKTtcbiAgcmV0dXJuIGZhY3RvcnkuY3JlYXRlKGNvZGUsIHtcbiAgICBhcHBOYW1lOiBhdXRoLm5hbWVcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcihcbiAgYXV0aDogQXV0aFxuKTogRmlyZWJhc2VFcnJvciB7XG4gIHJldHVybiBfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZShcbiAgICBhdXRoLFxuICAgIEF1dGhFcnJvckNvZGUuT1BFUkFUSU9OX05PVF9TVVBQT1JURUQsXG4gICAgJ09wZXJhdGlvbnMgdGhhdCBhbHRlciB0aGUgY3VycmVudCB1c2VyIGFyZSBub3Qgc3VwcG9ydGVkIGluIGNvbmp1bmN0aW9uIHdpdGggRmlyZWJhc2VTZXJ2ZXJBcHAnXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfYXNzZXJ0SW5zdGFuY2VPZihcbiAgYXV0aDogQXV0aCxcbiAgb2JqZWN0OiBvYmplY3QsXG4gIGluc3RhbmNlOiB1bmtub3duXG4pOiB2b2lkIHtcbiAgY29uc3QgY29uc3RydWN0b3JJbnN0YW5jZSA9IGluc3RhbmNlIGFzIHsgbmV3ICguLi5hcmdzOiB1bmtub3duW10pOiB1bmtub3duIH07XG4gIGlmICghKG9iamVjdCBpbnN0YW5jZW9mIGNvbnN0cnVjdG9ySW5zdGFuY2UpKSB7XG4gICAgaWYgKGNvbnN0cnVjdG9ySW5zdGFuY2UubmFtZSAhPT0gb2JqZWN0LmNvbnN0cnVjdG9yLm5hbWUpIHtcbiAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IpO1xuICAgIH1cblxuICAgIHRocm93IF9lcnJvcldpdGhDdXN0b21NZXNzYWdlKFxuICAgICAgYXV0aCxcbiAgICAgIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IsXG4gICAgICBgVHlwZSBvZiAke29iamVjdC5jb25zdHJ1Y3Rvci5uYW1lfSBkb2VzIG5vdCBtYXRjaCBleHBlY3RlZCBpbnN0YW5jZS5gICtcbiAgICAgICAgYERpZCB5b3UgcGFzcyBhIHJlZmVyZW5jZSBmcm9tIGEgZGlmZmVyZW50IEF1dGggU0RLP2BcbiAgICApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUVycm9ySW50ZXJuYWw8SyBleHRlbmRzIEF1dGhFcnJvckNvZGU+KFxuICBhdXRoT3JDb2RlOiBBdXRoIHwgSyxcbiAgLi4ucmVzdDogdW5rbm93bltdXG4pOiBGaXJlYmFzZUVycm9yIHtcbiAgaWYgKHR5cGVvZiBhdXRoT3JDb2RlICE9PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGNvZGUgPSByZXN0WzBdIGFzIEs7XG4gICAgY29uc3QgZnVsbFBhcmFtcyA9IFsuLi5yZXN0LnNsaWNlKDEpXSBhcyBBdXRoRXJyb3JMaXN0UGFyYW1zPEs+O1xuICAgIGlmIChmdWxsUGFyYW1zWzBdKSB7XG4gICAgICBmdWxsUGFyYW1zWzBdLmFwcE5hbWUgPSBhdXRoT3JDb2RlLm5hbWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIChhdXRoT3JDb2RlIGFzIEF1dGhJbnRlcm5hbCkuX2Vycm9yRmFjdG9yeS5jcmVhdGUoXG4gICAgICBjb2RlLFxuICAgICAgLi4uZnVsbFBhcmFtc1xuICAgICk7XG4gIH1cblxuICByZXR1cm4gX0RFRkFVTFRfQVVUSF9FUlJPUl9GQUNUT1JZLmNyZWF0ZShcbiAgICBhdXRoT3JDb2RlLFxuICAgIC4uLihyZXN0IGFzIEF1dGhFcnJvckxpc3RQYXJhbXM8Sz4pXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfYXNzZXJ0PEsgZXh0ZW5kcyBBdXRoRXJyb3JDb2RlPihcbiAgYXNzZXJ0aW9uOiB1bmtub3duLFxuICBjb2RlOiBLLFxuICAuLi5kYXRhOiB7fSBleHRlbmRzIEF1dGhFcnJvclBhcmFtc1tLXVxuICAgID8gW0F1dGhFcnJvclBhcmFtc1tLXT9dXG4gICAgOiBbQXV0aEVycm9yUGFyYW1zW0tdXVxuKTogYXNzZXJ0cyBhc3NlcnRpb247XG5leHBvcnQgZnVuY3Rpb24gX2Fzc2VydDxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGFzc2VydGlvbjogdW5rbm93bixcbiAgYXV0aDogQXV0aCxcbiAgY29kZTogSyxcbiAgLi4uZGF0YToge30gZXh0ZW5kcyBMZXNzQXBwTmFtZTxLPiA/IFtMZXNzQXBwTmFtZTxLPj9dIDogW0xlc3NBcHBOYW1lPEs+XVxuKTogYXNzZXJ0cyBhc3NlcnRpb247XG5leHBvcnQgZnVuY3Rpb24gX2Fzc2VydDxLIGV4dGVuZHMgQXV0aEVycm9yQ29kZT4oXG4gIGFzc2VydGlvbjogdW5rbm93bixcbiAgYXV0aE9yQ29kZTogQXV0aCB8IEssXG4gIC4uLnJlc3Q6IHVua25vd25bXVxuKTogYXNzZXJ0cyBhc3NlcnRpb24ge1xuICBpZiAoIWFzc2VydGlvbikge1xuICAgIHRocm93IGNyZWF0ZUVycm9ySW50ZXJuYWwoYXV0aE9yQ29kZSwgLi4ucmVzdCk7XG4gIH1cbn1cblxuLy8gV2UgcmVhbGx5IGRvIHdhbnQgdG8gYWNjZXB0IGxpdGVyYWxseSBhbnkgZnVuY3Rpb24gdHlwZSBoZXJlXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xudHlwZSBUeXBlRXhwZWN0YXRpb24gPSBGdW5jdGlvbiB8IHN0cmluZyB8IE1hcFR5cGU7XG5cbmludGVyZmFjZSBNYXBUeXBlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgVHlwZUV4cGVjdGF0aW9uIHwgT3B0aW9uYWw+IHt9XG5cbmNsYXNzIE9wdGlvbmFsIHtcbiAgY29uc3RydWN0b3IocmVhZG9ubHkgdHlwZTogVHlwZUV4cGVjdGF0aW9uKSB7fVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb3B0KHR5cGU6IFR5cGVFeHBlY3RhdGlvbik6IE9wdGlvbmFsIHtcbiAgcmV0dXJuIG5ldyBPcHRpb25hbCh0eXBlKTtcbn1cblxuLyoqXG4gKiBBc3NlcnRzIHRoZSBydW50aW1lIHR5cGVzIG9mIGFyZ3VtZW50cy4gVGhlICdleHBlY3RlZCcgZmllbGQgY2FuIGJlIG9uZSBvZlxuICogYSBjbGFzcywgYSBzdHJpbmcgKHJlcHJlc2VudGluZyBhIFwidHlwZW9mXCIgY2FsbCksIG9yIGEgcmVjb3JkIG1hcCBvZiBuYW1lXG4gKiB0byB0eXBlLiBGdXJ0aGVybW9yZSwgdGhlIG9wdCgpIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIHRvIG1hcmsgYSBmaWVsZCBhc1xuICogb3B0aW9uYWwuIEZvciBleGFtcGxlOlxuICpcbiAqIGZ1bmN0aW9uIGZvbyhhdXRoOiBBdXRoLCBwcm9maWxlOiB7ZGlzcGxheU5hbWU/OiBzdHJpbmd9LCB1cGRhdGUgPSBmYWxzZSkge1xuICogICBhc3NlcnRUeXBlcyhhcmd1bWVudHMsIFtBdXRoSW1wbCwge2Rpc3BsYXlOYW1lOiBvcHQoJ3N0cmluZycpfSwgb3B0KCdib29sZWFuJyldKTtcbiAqIH1cbiAqXG4gKiBvcHQoKSBjYW4gYmUgdXNlZCBmb3IgYW55IHR5cGU6XG4gKiBmdW5jdGlvbiBmb28oYXV0aD86IEF1dGgpIHtcbiAqICAgYXNzZXJ0VHlwZXMoYXJndW1lbnRzLCBbb3B0KEF1dGhJbXBsKV0pO1xuICogfVxuICpcbiAqIFRoZSBzdHJpbmcgdHlwZXMgY2FuIGJlIG9yJ2QgdG9nZXRoZXIsIGFuZCB5b3UgY2FuIHVzZSBcIm51bGxcIiBhcyB3ZWxsIChub3RlXG4gKiB0aGF0IHR5cGVvZiBudWxsID09PSAnb2JqZWN0JzsgdGhpcyBpcyBhbiBlZGdlIGNhc2UpLiBGb3IgZXhhbXBsZTpcbiAqXG4gKiBmdW5jdGlvbiBmb28ocHJvZmlsZToge2Rpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbH0pIHtcbiAqICAgYXNzZXJ0VHlwZXMoYXJndW1lbnRzLCBbe2Rpc3BsYXlOYW1lOiBvcHQoJ3N0cmluZ3xudWxsJyl9XSk7XG4gKiB9XG4gKlxuICogQHBhcmFtIGFyZ3NcbiAqIEBwYXJhbSBleHBlY3RlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0VHlwZXMoXG4gIGFyZ3M6IE9taXQ8SUFyZ3VtZW50cywgJ2NhbGxlZSc+LFxuICAuLi5leHBlY3RlZDogQXJyYXk8VHlwZUV4cGVjdGF0aW9uIHwgT3B0aW9uYWw+XG4pOiB2b2lkIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID4gZXhwZWN0ZWQubGVuZ3RoKSB7XG4gICAgX2ZhaWwoQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUiwge30pO1xuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBleHBlY3RlZC5sZW5ndGg7IGkrKykge1xuICAgIGxldCBleHBlY3QgPSBleHBlY3RlZFtpXTtcbiAgICBjb25zdCBhcmcgPSBhcmdzW2ldO1xuXG4gICAgaWYgKGV4cGVjdCBpbnN0YW5jZW9mIE9wdGlvbmFsKSB7XG4gICAgICAvLyBJZiB0aGUgYXJnIGlzIHVuZGVmaW5lZCwgdGhlbiBpdCBtYXRjaGVzIFwib3B0aW9uYWxcIiBhbmQgd2UgY2FuIG1vdmUgdG9cbiAgICAgIC8vIHRoZSBuZXh0IGFyZ1xuICAgICAgaWYgKHR5cGVvZiBhcmcgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgZXhwZWN0ID0gZXhwZWN0LnR5cGU7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBleHBlY3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBIYW5kbGUgdGhlIGVkZ2UgY2FzZSBmb3IgbnVsbCBiZWNhdXNlIHR5cGVvZiBudWxsID09PSAnb2JqZWN0J1xuICAgICAgaWYgKGV4cGVjdC5pbmNsdWRlcygnbnVsbCcpICYmIGFyZyA9PT0gbnVsbCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVxdWlyZWQgPSBleHBlY3Quc3BsaXQoJ3wnKTtcbiAgICAgIF9hc3NlcnQocmVxdWlyZWQuaW5jbHVkZXModHlwZW9mIGFyZyksIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IsIHt9KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBlY3QgPT09ICdvYmplY3QnKSB7XG4gICAgICAvLyBSZWN1cnNpdmVseSBjaGVjayByZWNvcmQgYXJndW1lbnRzXG4gICAgICBjb25zdCByZWNvcmQgPSBhcmcgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICBjb25zdCBtYXAgPSBleHBlY3QgYXMgTWFwVHlwZTtcbiAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhleHBlY3QpO1xuXG4gICAgICBhc3NlcnRUeXBlcyhcbiAgICAgICAga2V5cy5tYXAoayA9PiByZWNvcmRba10pLFxuICAgICAgICAuLi5rZXlzLm1hcChrID0+IG1hcFtrXSlcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIF9hc3NlcnQoYXJnIGluc3RhbmNlb2YgZXhwZWN0LCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SLCB7fSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVW5jb25kaXRpb25hbGx5IGZhaWxzLCB0aHJvd2luZyBhbiBpbnRlcm5hbCBlcnJvciB3aXRoIHRoZSBnaXZlbiBtZXNzYWdlLlxuICpcbiAqIEBwYXJhbSBmYWlsdXJlIHR5cGUgb2YgZmFpbHVyZSBlbmNvdW50ZXJlZFxuICogQHRocm93cyBFcnJvclxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdGYWlsKGZhaWx1cmU6IHN0cmluZyk6IG5ldmVyIHtcbiAgLy8gTG9nIHRoZSBmYWlsdXJlIGluIGFkZGl0aW9uIHRvIHRocm93IGFuIGV4Y2VwdGlvbiwganVzdCBpbiBjYXNlIHRoZVxuICAvLyBleGNlcHRpb24gaXMgc3dhbGxvd2VkLlxuICBjb25zdCBtZXNzYWdlID0gYElOVEVSTkFMIEFTU0VSVElPTiBGQUlMRUQ6IGAgKyBmYWlsdXJlO1xuICBfbG9nRXJyb3IobWVzc2FnZSk7XG5cbiAgLy8gTk9URTogV2UgZG9uJ3QgdXNlIEZpcmViYXNlRXJyb3IgaGVyZSBiZWNhdXNlIHRoZXNlIGFyZSBpbnRlcm5hbCBmYWlsdXJlc1xuICAvLyB0aGF0IGNhbm5vdCBiZSBoYW5kbGVkIGJ5IHRoZSB1c2VyLiAoQWxzbyBpdCB3b3VsZCBjcmVhdGUgYSBjaXJjdWxhclxuICAvLyBkZXBlbmRlbmN5IGJldHdlZW4gdGhlIGVycm9yIGFuZCBhc3NlcnQgbW9kdWxlcyB3aGljaCBkb2Vzbid0IHdvcmsuKVxuICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRmFpbHMgaWYgdGhlIGdpdmVuIGFzc2VydGlvbiBjb25kaXRpb24gaXMgZmFsc2UsIHRocm93aW5nIGFuIEVycm9yIHdpdGggdGhlXG4gKiBnaXZlbiBtZXNzYWdlIGlmIGl0IGRpZC5cbiAqXG4gKiBAcGFyYW0gYXNzZXJ0aW9uXG4gKiBAcGFyYW0gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdBc3NlcnQoXG4gIGFzc2VydGlvbjogdW5rbm93bixcbiAgbWVzc2FnZTogc3RyaW5nXG4pOiBhc3NlcnRzIGFzc2VydGlvbiB7XG4gIGlmICghYXNzZXJ0aW9uKSB7XG4gICAgZGVidWdGYWlsKG1lc3NhZ2UpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIF9nZXRDdXJyZW50VXJsKCk6IHN0cmluZyB7XG4gIHJldHVybiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHNlbGYubG9jYXRpb24/LmhyZWYpIHx8ICcnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSHR0cE9ySHR0cHMoKTogYm9vbGVhbiB7XG4gIHJldHVybiBfZ2V0Q3VycmVudFNjaGVtZSgpID09PSAnaHR0cDonIHx8IF9nZXRDdXJyZW50U2NoZW1lKCkgPT09ICdodHRwczonO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2dldEN1cnJlbnRTY2hlbWUoKTogc3RyaW5nIHwgbnVsbCB7XG4gIHJldHVybiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHNlbGYubG9jYXRpb24/LnByb3RvY29sKSB8fCBudWxsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGlzQnJvd3NlckV4dGVuc2lvbiB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IF9pc0h0dHBPckh0dHBzIH0gZnJvbSAnLi9sb2NhdGlvbic7XG5cbi8qKlxuICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhlIGJyb3dzZXIgaXMgd29ya2luZyBvbmxpbmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9pc09ubGluZSgpOiBib29sZWFuIHtcbiAgaWYgKFxuICAgIHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmXG4gICAgbmF2aWdhdG9yICYmXG4gICAgJ29uTGluZScgaW4gbmF2aWdhdG9yICYmXG4gICAgdHlwZW9mIG5hdmlnYXRvci5vbkxpbmUgPT09ICdib29sZWFuJyAmJlxuICAgIC8vIEFwcGx5IG9ubHkgZm9yIHRyYWRpdGlvbmFsIHdlYiBhcHBzIGFuZCBDaHJvbWUgZXh0ZW5zaW9ucy5cbiAgICAvLyBUaGlzIGlzIGVzcGVjaWFsbHkgdHJ1ZSBmb3IgQ29yZG92YSBhcHBzIHdoaWNoIGhhdmUgdW5yZWxpYWJsZVxuICAgIC8vIG5hdmlnYXRvci5vbkxpbmUgYmVoYXZpb3IgdW5sZXNzIGNvcmRvdmEtcGx1Z2luLW5ldHdvcmstaW5mb3JtYXRpb24gaXNcbiAgICAvLyBpbnN0YWxsZWQgd2hpY2ggb3ZlcndyaXRlcyB0aGUgbmF0aXZlIG5hdmlnYXRvci5vbkxpbmUgdmFsdWUgYW5kXG4gICAgLy8gZGVmaW5lcyBuYXZpZ2F0b3IuY29ubmVjdGlvbi5cbiAgICAoX2lzSHR0cE9ySHR0cHMoKSB8fCBpc0Jyb3dzZXJFeHRlbnNpb24oKSB8fCAnY29ubmVjdGlvbicgaW4gbmF2aWdhdG9yKVxuICApIHtcbiAgICByZXR1cm4gbmF2aWdhdG9yLm9uTGluZTtcbiAgfVxuICAvLyBJZiB3ZSBjYW4ndCBkZXRlcm1pbmUgdGhlIHN0YXRlLCBhc3N1bWUgaXQgaXMgb25saW5lLlxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9nZXRVc2VyTGFuZ3VhZ2UoKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IG5hdmlnYXRvckxhbmd1YWdlOiBOYXZpZ2F0b3JMYW5ndWFnZSA9IG5hdmlnYXRvcjtcbiAgcmV0dXJuIChcbiAgICAvLyBNb3N0IHJlbGlhYmxlLCBidXQgb25seSBzdXBwb3J0ZWQgaW4gQ2hyb21lL0ZpcmVmb3guXG4gICAgKG5hdmlnYXRvckxhbmd1YWdlLmxhbmd1YWdlcyAmJiBuYXZpZ2F0b3JMYW5ndWFnZS5sYW5ndWFnZXNbMF0pIHx8XG4gICAgLy8gU3VwcG9ydGVkIGluIG1vc3QgYnJvd3NlcnMsIGJ1dCByZXR1cm5zIHRoZSBsYW5ndWFnZSBvZiB0aGUgYnJvd3NlclxuICAgIC8vIFVJLCBub3QgdGhlIGxhbmd1YWdlIHNldCBpbiBicm93c2VyIHNldHRpbmdzLlxuICAgIG5hdmlnYXRvckxhbmd1YWdlLmxhbmd1YWdlIHx8XG4gICAgLy8gQ291bGRuJ3QgZGV0ZXJtaW5lIGxhbmd1YWdlLlxuICAgIG51bGxcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBpc01vYmlsZUNvcmRvdmEsIGlzUmVhY3ROYXRpdmUgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBfaXNPbmxpbmUgfSBmcm9tICcuL25hdmlnYXRvcic7XG5pbXBvcnQgeyBkZWJ1Z0Fzc2VydCB9IGZyb20gJy4vYXNzZXJ0JztcblxuZXhwb3J0IGNvbnN0IGVudW0gRGVsYXlNaW4ge1xuICBPRkZMSU5FID0gNTAwMFxufVxuXG4vKipcbiAqIEEgc3RydWN0dXJlIHRvIGhlbHAgcGljayBiZXR3ZWVuIGEgcmFuZ2Ugb2YgbG9uZyBhbmQgc2hvcnQgZGVsYXkgZHVyYXRpb25zXG4gKiBkZXBlbmRpbmcgb24gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIEluIGdlbmVyYWwsIHRoZSBsb25nIGRlbGF5IGlzIHVzZWQgZm9yXG4gKiBtb2JpbGUgZW52aXJvbm1lbnRzIHdoZXJlYXMgc2hvcnQgZGVsYXlzIGFyZSB1c2VkIGZvciBkZXNrdG9wIGVudmlyb25tZW50cy5cbiAqL1xuZXhwb3J0IGNsYXNzIERlbGF5IHtcbiAgLy8gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBvZmZsaW5lIGRlbGF5IHRpbWVvdXQgaW4gbXMuXG5cbiAgcHJpdmF0ZSByZWFkb25seSBpc01vYmlsZTogYm9vbGVhbjtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzaG9ydERlbGF5OiBudW1iZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBsb25nRGVsYXk6IG51bWJlclxuICApIHtcbiAgICAvLyBJbnRlcm5hbCBlcnJvciB3aGVuIGltcHJvcGVybHkgaW5pdGlhbGl6ZWQuXG4gICAgZGVidWdBc3NlcnQoXG4gICAgICBsb25nRGVsYXkgPiBzaG9ydERlbGF5LFxuICAgICAgJ1Nob3J0IGRlbGF5IHNob3VsZCBiZSBsZXNzIHRoYW4gbG9uZyBkZWxheSEnXG4gICAgKTtcbiAgICB0aGlzLmlzTW9iaWxlID0gaXNNb2JpbGVDb3Jkb3ZhKCkgfHwgaXNSZWFjdE5hdGl2ZSgpO1xuICB9XG5cbiAgZ2V0KCk6IG51bWJlciB7XG4gICAgaWYgKCFfaXNPbmxpbmUoKSkge1xuICAgICAgLy8gUGljayB0aGUgc2hvcnRlciB0aW1lb3V0LlxuICAgICAgcmV0dXJuIE1hdGgubWluKERlbGF5TWluLk9GRkxJTkUsIHRoaXMuc2hvcnREZWxheSk7XG4gICAgfVxuICAgIC8vIElmIHJ1bm5pbmcgaW4gYSBtb2JpbGUgZW52aXJvbm1lbnQsIHJldHVybiB0aGUgbG9uZyBkZWxheSwgb3RoZXJ3aXNlXG4gICAgLy8gcmV0dXJuIHRoZSBzaG9ydCBkZWxheS5cbiAgICAvLyBUaGlzIGNvdWxkIGJlIGltcHJvdmVkIGluIHRoZSBmdXR1cmUgdG8gZHluYW1pY2FsbHkgY2hhbmdlIGJhc2VkIG9uIG90aGVyXG4gICAgLy8gdmFyaWFibGVzIGluc3RlYWQgb2YganVzdCByZWFkaW5nIHRoZSBjdXJyZW50IGVudmlyb25tZW50LlxuICAgIHJldHVybiB0aGlzLmlzTW9iaWxlID8gdGhpcy5sb25nRGVsYXkgOiB0aGlzLnNob3J0RGVsYXk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgZGVidWdBc3NlcnQgfSBmcm9tICcuL2Fzc2VydCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBfZW11bGF0b3JVcmwoY29uZmlnOiBDb25maWdJbnRlcm5hbCwgcGF0aD86IHN0cmluZyk6IHN0cmluZyB7XG4gIGRlYnVnQXNzZXJ0KGNvbmZpZy5lbXVsYXRvciwgJ0VtdWxhdG9yIHNob3VsZCBhbHdheXMgYmUgc2V0IGhlcmUnKTtcbiAgY29uc3QgeyB1cmwgfSA9IGNvbmZpZy5lbXVsYXRvcjtcblxuICBpZiAoIXBhdGgpIHtcbiAgICByZXR1cm4gdXJsO1xuICB9XG5cbiAgcmV0dXJuIGAke3VybH0ke3BhdGguc3RhcnRzV2l0aCgnLycpID8gcGF0aC5zbGljZSgxKSA6IHBhdGh9YDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBkZWJ1Z0ZhaWwgfSBmcm9tICcuL2Fzc2VydCc7XG5cbmV4cG9ydCBjbGFzcyBGZXRjaFByb3ZpZGVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgZmV0Y2hJbXBsOiB0eXBlb2YgZmV0Y2ggfCBudWxsO1xuICBwcml2YXRlIHN0YXRpYyBoZWFkZXJzSW1wbDogdHlwZW9mIEhlYWRlcnMgfCBudWxsO1xuICBwcml2YXRlIHN0YXRpYyByZXNwb25zZUltcGw6IHR5cGVvZiBSZXNwb25zZSB8IG51bGw7XG5cbiAgc3RhdGljIGluaXRpYWxpemUoXG4gICAgZmV0Y2hJbXBsOiB0eXBlb2YgZmV0Y2gsXG4gICAgaGVhZGVyc0ltcGw/OiB0eXBlb2YgSGVhZGVycyxcbiAgICByZXNwb25zZUltcGw/OiB0eXBlb2YgUmVzcG9uc2VcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5mZXRjaEltcGwgPSBmZXRjaEltcGw7XG4gICAgaWYgKGhlYWRlcnNJbXBsKSB7XG4gICAgICB0aGlzLmhlYWRlcnNJbXBsID0gaGVhZGVyc0ltcGw7XG4gICAgfVxuICAgIGlmIChyZXNwb25zZUltcGwpIHtcbiAgICAgIHRoaXMucmVzcG9uc2VJbXBsID0gcmVzcG9uc2VJbXBsO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBmZXRjaCgpOiB0eXBlb2YgZmV0Y2gge1xuICAgIGlmICh0aGlzLmZldGNoSW1wbCkge1xuICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hJbXBsO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmICdmZXRjaCcgaW4gc2VsZikge1xuICAgICAgcmV0dXJuIHNlbGYuZmV0Y2g7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgJiYgZ2xvYmFsVGhpcy5mZXRjaCkge1xuICAgICAgcmV0dXJuIGdsb2JhbFRoaXMuZmV0Y2g7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZmV0Y2ggIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZmV0Y2g7XG4gICAgfVxuICAgIGRlYnVnRmFpbChcbiAgICAgICdDb3VsZCBub3QgZmluZCBmZXRjaCBpbXBsZW1lbnRhdGlvbiwgbWFrZSBzdXJlIHlvdSBjYWxsIEZldGNoUHJvdmlkZXIuaW5pdGlhbGl6ZSgpIHdpdGggYW4gYXBwcm9wcmlhdGUgcG9seWZpbGwnXG4gICAgKTtcbiAgfVxuXG4gIHN0YXRpYyBoZWFkZXJzKCk6IHR5cGVvZiBIZWFkZXJzIHtcbiAgICBpZiAodGhpcy5oZWFkZXJzSW1wbCkge1xuICAgICAgcmV0dXJuIHRoaXMuaGVhZGVyc0ltcGw7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgJiYgJ0hlYWRlcnMnIGluIHNlbGYpIHtcbiAgICAgIHJldHVybiBzZWxmLkhlYWRlcnM7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgJiYgZ2xvYmFsVGhpcy5IZWFkZXJzKSB7XG4gICAgICByZXR1cm4gZ2xvYmFsVGhpcy5IZWFkZXJzO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIEhlYWRlcnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gSGVhZGVycztcbiAgICB9XG4gICAgZGVidWdGYWlsKFxuICAgICAgJ0NvdWxkIG5vdCBmaW5kIEhlYWRlcnMgaW1wbGVtZW50YXRpb24sIG1ha2Ugc3VyZSB5b3UgY2FsbCBGZXRjaFByb3ZpZGVyLmluaXRpYWxpemUoKSB3aXRoIGFuIGFwcHJvcHJpYXRlIHBvbHlmaWxsJ1xuICAgICk7XG4gIH1cblxuICBzdGF0aWMgcmVzcG9uc2UoKTogdHlwZW9mIFJlc3BvbnNlIHtcbiAgICBpZiAodGhpcy5yZXNwb25zZUltcGwpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlc3BvbnNlSW1wbDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyAmJiAnUmVzcG9uc2UnIGluIHNlbGYpIHtcbiAgICAgIHJldHVybiBzZWxmLlJlc3BvbnNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbFRoaXMuUmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiBnbG9iYWxUaGlzLlJlc3BvbnNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIFJlc3BvbnNlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIFJlc3BvbnNlO1xuICAgIH1cbiAgICBkZWJ1Z0ZhaWwoXG4gICAgICAnQ291bGQgbm90IGZpbmQgUmVzcG9uc2UgaW1wbGVtZW50YXRpb24sIG1ha2Ugc3VyZSB5b3UgY2FsbCBGZXRjaFByb3ZpZGVyLmluaXRpYWxpemUoKSB3aXRoIGFuIGFwcHJvcHJpYXRlIHBvbHlmaWxsJ1xuICAgICk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuXG4vKipcbiAqIEVycm9ycyB0aGF0IGNhbiBiZSByZXR1cm5lZCBieSB0aGUgYmFja2VuZFxuICovXG5leHBvcnQgY29uc3QgZW51bSBTZXJ2ZXJFcnJvciB7XG4gIEFETUlOX09OTFlfT1BFUkFUSU9OID0gJ0FETUlOX09OTFlfT1BFUkFUSU9OJyxcbiAgQkxPQ0tJTkdfRlVOQ1RJT05fRVJST1JfUkVTUE9OU0UgPSAnQkxPQ0tJTkdfRlVOQ1RJT05fRVJST1JfUkVTUE9OU0UnLFxuICBDQVBUQ0hBX0NIRUNLX0ZBSUxFRCA9ICdDQVBUQ0hBX0NIRUNLX0ZBSUxFRCcsXG4gIENPUlNfVU5TVVBQT1JURUQgPSAnQ09SU19VTlNVUFBPUlRFRCcsXG4gIENSRURFTlRJQUxfTUlTTUFUQ0ggPSAnQ1JFREVOVElBTF9NSVNNQVRDSCcsXG4gIENSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTiA9ICdDUkVERU5USUFMX1RPT19PTERfTE9HSU5fQUdBSU4nLFxuICBEWU5BTUlDX0xJTktfTk9UX0FDVElWQVRFRCA9ICdEWU5BTUlDX0xJTktfTk9UX0FDVElWQVRFRCcsXG4gIEVNQUlMX0NIQU5HRV9ORUVEU19WRVJJRklDQVRJT04gPSAnRU1BSUxfQ0hBTkdFX05FRURTX1ZFUklGSUNBVElPTicsXG4gIEVNQUlMX0VYSVNUUyA9ICdFTUFJTF9FWElTVFMnLFxuICBFTUFJTF9OT1RfRk9VTkQgPSAnRU1BSUxfTk9UX0ZPVU5EJyxcbiAgRVhQSVJFRF9PT0JfQ09ERSA9ICdFWFBJUkVEX09PQl9DT0RFJyxcbiAgRkVERVJBVEVEX1VTRVJfSURfQUxSRUFEWV9MSU5LRUQgPSAnRkVERVJBVEVEX1VTRVJfSURfQUxSRUFEWV9MSU5LRUQnLFxuICBJTlZBTElEX0FQUF9DUkVERU5USUFMID0gJ0lOVkFMSURfQVBQX0NSRURFTlRJQUwnLFxuICBJTlZBTElEX0FQUF9JRCA9ICdJTlZBTElEX0FQUF9JRCcsXG4gIElOVkFMSURfQ0VSVF9IQVNIID0gJ0lOVkFMSURfQ0VSVF9IQVNIJyxcbiAgSU5WQUxJRF9DT0RFID0gJ0lOVkFMSURfQ09ERScsXG4gIElOVkFMSURfQ09OVElOVUVfVVJJID0gJ0lOVkFMSURfQ09OVElOVUVfVVJJJyxcbiAgSU5WQUxJRF9DVVNUT01fVE9LRU4gPSAnSU5WQUxJRF9DVVNUT01fVE9LRU4nLFxuICBJTlZBTElEX0RZTkFNSUNfTElOS19ET01BSU4gPSAnSU5WQUxJRF9EWU5BTUlDX0xJTktfRE9NQUlOJyxcbiAgSU5WQUxJRF9FTUFJTCA9ICdJTlZBTElEX0VNQUlMJyxcbiAgSU5WQUxJRF9JRF9UT0tFTiA9ICdJTlZBTElEX0lEX1RPS0VOJyxcbiAgSU5WQUxJRF9JRFBfUkVTUE9OU0UgPSAnSU5WQUxJRF9JRFBfUkVTUE9OU0UnLFxuICBJTlZBTElEX0lERU5USUZJRVIgPSAnSU5WQUxJRF9JREVOVElGSUVSJyxcbiAgSU5WQUxJRF9MT0dJTl9DUkVERU5USUFMUyA9ICdJTlZBTElEX0xPR0lOX0NSRURFTlRJQUxTJyxcbiAgSU5WQUxJRF9NRVNTQUdFX1BBWUxPQUQgPSAnSU5WQUxJRF9NRVNTQUdFX1BBWUxPQUQnLFxuICBJTlZBTElEX01GQV9QRU5ESU5HX0NSRURFTlRJQUwgPSAnSU5WQUxJRF9NRkFfUEVORElOR19DUkVERU5USUFMJyxcbiAgSU5WQUxJRF9PQVVUSF9DTElFTlRfSUQgPSAnSU5WQUxJRF9PQVVUSF9DTElFTlRfSUQnLFxuICBJTlZBTElEX09PQl9DT0RFID0gJ0lOVkFMSURfT09CX0NPREUnLFxuICBJTlZBTElEX1BBU1NXT1JEID0gJ0lOVkFMSURfUEFTU1dPUkQnLFxuICBJTlZBTElEX1BFTkRJTkdfVE9LRU4gPSAnSU5WQUxJRF9QRU5ESU5HX1RPS0VOJyxcbiAgSU5WQUxJRF9QSE9ORV9OVU1CRVIgPSAnSU5WQUxJRF9QSE9ORV9OVU1CRVInLFxuICBJTlZBTElEX1BST1ZJREVSX0lEID0gJ0lOVkFMSURfUFJPVklERVJfSUQnLFxuICBJTlZBTElEX1JFQ0lQSUVOVF9FTUFJTCA9ICdJTlZBTElEX1JFQ0lQSUVOVF9FTUFJTCcsXG4gIElOVkFMSURfU0VOREVSID0gJ0lOVkFMSURfU0VOREVSJyxcbiAgSU5WQUxJRF9TRVNTSU9OX0lORk8gPSAnSU5WQUxJRF9TRVNTSU9OX0lORk8nLFxuICBJTlZBTElEX1RFTVBPUkFSWV9QUk9PRiA9ICdJTlZBTElEX1RFTVBPUkFSWV9QUk9PRicsXG4gIElOVkFMSURfVEVOQU5UX0lEID0gJ0lOVkFMSURfVEVOQU5UX0lEJyxcbiAgTUZBX0VOUk9MTE1FTlRfTk9UX0ZPVU5EID0gJ01GQV9FTlJPTExNRU5UX05PVF9GT1VORCcsXG4gIE1JU1NJTkdfQU5EUk9JRF9QQUNLQUdFX05BTUUgPSAnTUlTU0lOR19BTkRST0lEX1BBQ0tBR0VfTkFNRScsXG4gIE1JU1NJTkdfQVBQX0NSRURFTlRJQUwgPSAnTUlTU0lOR19BUFBfQ1JFREVOVElBTCcsXG4gIE1JU1NJTkdfQ09ERSA9ICdNSVNTSU5HX0NPREUnLFxuICBNSVNTSU5HX0NPTlRJTlVFX1VSSSA9ICdNSVNTSU5HX0NPTlRJTlVFX1VSSScsXG4gIE1JU1NJTkdfQ1VTVE9NX1RPS0VOID0gJ01JU1NJTkdfQ1VTVE9NX1RPS0VOJyxcbiAgTUlTU0lOR19JT1NfQlVORExFX0lEID0gJ01JU1NJTkdfSU9TX0JVTkRMRV9JRCcsXG4gIE1JU1NJTkdfTUZBX0VOUk9MTE1FTlRfSUQgPSAnTUlTU0lOR19NRkFfRU5ST0xMTUVOVF9JRCcsXG4gIE1JU1NJTkdfTUZBX1BFTkRJTkdfQ1JFREVOVElBTCA9ICdNSVNTSU5HX01GQV9QRU5ESU5HX0NSRURFTlRJQUwnLFxuICBNSVNTSU5HX09PQl9DT0RFID0gJ01JU1NJTkdfT09CX0NPREUnLFxuICBNSVNTSU5HX09SX0lOVkFMSURfTk9OQ0UgPSAnTUlTU0lOR19PUl9JTlZBTElEX05PTkNFJyxcbiAgTUlTU0lOR19QQVNTV09SRCA9ICdNSVNTSU5HX1BBU1NXT1JEJyxcbiAgTUlTU0lOR19SRVFfVFlQRSA9ICdNSVNTSU5HX1JFUV9UWVBFJyxcbiAgTUlTU0lOR19QSE9ORV9OVU1CRVIgPSAnTUlTU0lOR19QSE9ORV9OVU1CRVInLFxuICBNSVNTSU5HX1NFU1NJT05fSU5GTyA9ICdNSVNTSU5HX1NFU1NJT05fSU5GTycsXG4gIE9QRVJBVElPTl9OT1RfQUxMT1dFRCA9ICdPUEVSQVRJT05fTk9UX0FMTE9XRUQnLFxuICBQQVNTV09SRF9MT0dJTl9ESVNBQkxFRCA9ICdQQVNTV09SRF9MT0dJTl9ESVNBQkxFRCcsXG4gIFFVT1RBX0VYQ0VFREVEID0gJ1FVT1RBX0VYQ0VFREVEJyxcbiAgUkVTRVRfUEFTU1dPUkRfRVhDRUVEX0xJTUlUID0gJ1JFU0VUX1BBU1NXT1JEX0VYQ0VFRF9MSU1JVCcsXG4gIFJFSkVDVEVEX0NSRURFTlRJQUwgPSAnUkVKRUNURURfQ1JFREVOVElBTCcsXG4gIFNFQ09ORF9GQUNUT1JfRVhJU1RTID0gJ1NFQ09ORF9GQUNUT1JfRVhJU1RTJyxcbiAgU0VDT05EX0ZBQ1RPUl9MSU1JVF9FWENFRURFRCA9ICdTRUNPTkRfRkFDVE9SX0xJTUlUX0VYQ0VFREVEJyxcbiAgU0VTU0lPTl9FWFBJUkVEID0gJ1NFU1NJT05fRVhQSVJFRCcsXG4gIFRFTkFOVF9JRF9NSVNNQVRDSCA9ICdURU5BTlRfSURfTUlTTUFUQ0gnLFxuICBUT0tFTl9FWFBJUkVEID0gJ1RPS0VOX0VYUElSRUQnLFxuICBUT09fTUFOWV9BVFRFTVBUU19UUllfTEFURVIgPSAnVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSJyxcbiAgVU5TVVBQT1JURURfRklSU1RfRkFDVE9SID0gJ1VOU1VQUE9SVEVEX0ZJUlNUX0ZBQ1RPUicsXG4gIFVOU1VQUE9SVEVEX1RFTkFOVF9PUEVSQVRJT04gPSAnVU5TVVBQT1JURURfVEVOQU5UX09QRVJBVElPTicsXG4gIFVOQVVUSE9SSVpFRF9ET01BSU4gPSAnVU5BVVRIT1JJWkVEX0RPTUFJTicsXG4gIFVOVkVSSUZJRURfRU1BSUwgPSAnVU5WRVJJRklFRF9FTUFJTCcsXG4gIFVTRVJfQ0FOQ0VMTEVEID0gJ1VTRVJfQ0FOQ0VMTEVEJyxcbiAgVVNFUl9ESVNBQkxFRCA9ICdVU0VSX0RJU0FCTEVEJyxcbiAgVVNFUl9OT1RfRk9VTkQgPSAnVVNFUl9OT1RfRk9VTkQnLFxuICBXRUFLX1BBU1NXT1JEID0gJ1dFQUtfUEFTU1dPUkQnLFxuICBSRUNBUFRDSEFfTk9UX0VOQUJMRUQgPSAnUkVDQVBUQ0hBX05PVF9FTkFCTEVEJyxcbiAgTUlTU0lOR19SRUNBUFRDSEFfVE9LRU4gPSAnTUlTU0lOR19SRUNBUFRDSEFfVE9LRU4nLFxuICBJTlZBTElEX1JFQ0FQVENIQV9UT0tFTiA9ICdJTlZBTElEX1JFQ0FQVENIQV9UT0tFTicsXG4gIElOVkFMSURfUkVDQVBUQ0hBX0FDVElPTiA9ICdJTlZBTElEX1JFQ0FQVENIQV9BQ1RJT04nLFxuICBNSVNTSU5HX0NMSUVOVF9UWVBFID0gJ01JU1NJTkdfQ0xJRU5UX1RZUEUnLFxuICBNSVNTSU5HX1JFQ0FQVENIQV9WRVJTSU9OID0gJ01JU1NJTkdfUkVDQVBUQ0hBX1ZFUlNJT04nLFxuICBJTlZBTElEX1JFQ0FQVENIQV9WRVJTSU9OID0gJ0lOVkFMSURfUkVDQVBUQ0hBX1ZFUlNJT04nLFxuICBJTlZBTElEX1JFUV9UWVBFID0gJ0lOVkFMSURfUkVRX1RZUEUnLFxuICBQQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UUyA9ICdQQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UUycsXG4gIElOVkFMSURfSE9TVElOR19MSU5LX0RPTUFJTiA9ICdJTlZBTElEX0hPU1RJTkdfTElOS19ET01BSU4nXG59XG5cbi8qKlxuICogQVBJIFJlc3BvbnNlIGluIHRoZSBldmVudCBvZiBhbiBlcnJvclxuICovXG5leHBvcnQgaW50ZXJmYWNlIEpzb25FcnJvciB7XG4gIGVycm9yOiB7XG4gICAgY29kZTogbnVtYmVyO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcbiAgICBlcnJvcnM/OiBbXG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6IFNlcnZlckVycm9yO1xuICAgICAgICBkb21haW46IHN0cmluZztcbiAgICAgICAgcmVhc29uOiBzdHJpbmc7XG4gICAgICB9XG4gICAgXTtcbiAgfTtcbn1cblxuLyoqXG4gKiBUeXBlIGRlZmluaXRpb24gZm9yIGEgbWFwIGZyb20gc2VydmVyIGVycm9ycyB0byBkZXZlbG9wZXIgdmlzaWJsZSBlcnJvcnNcbiAqL1xuZXhwb3J0IGRlY2xhcmUgdHlwZSBTZXJ2ZXJFcnJvck1hcDxBcGlFcnJvciBleHRlbmRzIHN0cmluZz4gPSB7XG4gIHJlYWRvbmx5IFtLIGluIEFwaUVycm9yXTogQXV0aEVycm9yQ29kZTtcbn07XG5cbi8qKlxuICogTWFwIGZyb20gZXJyb3JzIHJldHVybmVkIGJ5IHRoZSBzZXJ2ZXIgdG8gZXJyb3JzIHRvIGRldmVsb3BlciB2aXNpYmxlIGVycm9yc1xuICovXG5leHBvcnQgY29uc3QgU0VSVkVSX0VSUk9SX01BUDogUGFydGlhbDxTZXJ2ZXJFcnJvck1hcDxTZXJ2ZXJFcnJvcj4+ID0ge1xuICAvLyBDdXN0b20gdG9rZW4gZXJyb3JzLlxuICBbU2VydmVyRXJyb3IuQ1JFREVOVElBTF9NSVNNQVRDSF06IEF1dGhFcnJvckNvZGUuQ1JFREVOVElBTF9NSVNNQVRDSCxcbiAgLy8gVGhpcyBjYW4gb25seSBoYXBwZW4gaWYgdGhlIFNESyBzZW5kcyBhIGJhZCByZXF1ZXN0LlxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19DVVNUT01fVE9LRU5dOiBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuXG4gIC8vIENyZWF0ZSBBdXRoIFVSSSBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0lERU5USUZJRVJdOiBBdXRoRXJyb3JDb2RlLklOVkFMSURfRU1BSUwsXG4gIC8vIFRoaXMgY2FuIG9ubHkgaGFwcGVuIGlmIHRoZSBTREsgc2VuZHMgYSBiYWQgcmVxdWVzdC5cbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfQ09OVElOVUVfVVJJXTogQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUixcblxuICAvLyBTaWduIGluIHdpdGggZW1haWwgYW5kIHBhc3N3b3JkIGVycm9ycyAoc29tZSBhcHBseSB0byBzaWduIHVwIHRvbykuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX1BBU1NXT1JEXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX1BBU1NXT1JELFxuICAvLyBUaGlzIGNhbiBvbmx5IGhhcHBlbiBpZiB0aGUgU0RLIHNlbmRzIGEgYmFkIHJlcXVlc3QuXG4gIFtTZXJ2ZXJFcnJvci5NSVNTSU5HX1BBU1NXT1JEXTogQXV0aEVycm9yQ29kZS5NSVNTSU5HX1BBU1NXT1JELFxuICAvLyBUaHJvd24gaWYgRW1haWwgRW51bWVyYXRpb24gUHJvdGVjdGlvbiBpcyBlbmFibGVkIGluIHRoZSBwcm9qZWN0IGFuZCB0aGUgZW1haWwgb3IgcGFzc3dvcmQgaXNcbiAgLy8gaW52YWxpZC5cbiAgW1NlcnZlckVycm9yLklOVkFMSURfTE9HSU5fQ1JFREVOVElBTFNdOiBBdXRoRXJyb3JDb2RlLklOVkFMSURfQ1JFREVOVElBTCxcblxuICAvLyBTaWduIHVwIHdpdGggZW1haWwgYW5kIHBhc3N3b3JkIGVycm9ycy5cbiAgW1NlcnZlckVycm9yLkVNQUlMX0VYSVNUU106IEF1dGhFcnJvckNvZGUuRU1BSUxfRVhJU1RTLFxuICBbU2VydmVyRXJyb3IuUEFTU1dPUkRfTE9HSU5fRElTQUJMRURdOiBBdXRoRXJyb3JDb2RlLk9QRVJBVElPTl9OT1RfQUxMT1dFRCxcblxuICAvLyBWZXJpZnkgYXNzZXJ0aW9uIGZvciBzaWduIGluIHdpdGggY3JlZGVudGlhbCBlcnJvcnM6XG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0lEUF9SRVNQT05TRV06IEF1dGhFcnJvckNvZGUuSU5WQUxJRF9DUkVERU5USUFMLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9QRU5ESU5HX1RPS0VOXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX0NSRURFTlRJQUwsXG4gIFtTZXJ2ZXJFcnJvci5GRURFUkFURURfVVNFUl9JRF9BTFJFQURZX0xJTktFRF06XG4gICAgQXV0aEVycm9yQ29kZS5DUkVERU5USUFMX0FMUkVBRFlfSU5fVVNFLFxuXG4gIC8vIFRoaXMgY2FuIG9ubHkgaGFwcGVuIGlmIHRoZSBTREsgc2VuZHMgYSBiYWQgcmVxdWVzdC5cbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfUkVRX1RZUEVdOiBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuXG4gIC8vIFNlbmQgUGFzc3dvcmQgcmVzZXQgZW1haWwgZXJyb3JzOlxuICBbU2VydmVyRXJyb3IuRU1BSUxfTk9UX0ZPVU5EXTogQXV0aEVycm9yQ29kZS5VU0VSX0RFTEVURUQsXG4gIFtTZXJ2ZXJFcnJvci5SRVNFVF9QQVNTV09SRF9FWENFRURfTElNSVRdOlxuICAgIEF1dGhFcnJvckNvZGUuVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSLFxuXG4gIFtTZXJ2ZXJFcnJvci5FWFBJUkVEX09PQl9DT0RFXTogQXV0aEVycm9yQ29kZS5FWFBJUkVEX09PQl9DT0RFLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9PT0JfQ09ERV06IEF1dGhFcnJvckNvZGUuSU5WQUxJRF9PT0JfQ09ERSxcbiAgLy8gVGhpcyBjYW4gb25seSBoYXBwZW4gaWYgdGhlIFNESyBzZW5kcyBhIGJhZCByZXF1ZXN0LlxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19PT0JfQ09ERV06IEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IsXG5cbiAgLy8gT3BlcmF0aW9ucyB0aGF0IHJlcXVpcmUgSUQgdG9rZW4gaW4gcmVxdWVzdDpcbiAgW1NlcnZlckVycm9yLkNSRURFTlRJQUxfVE9PX09MRF9MT0dJTl9BR0FJTl06XG4gICAgQXV0aEVycm9yQ29kZS5DUkVERU5USUFMX1RPT19PTERfTE9HSU5fQUdBSU4sXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0lEX1RPS0VOXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX0FVVEgsXG4gIFtTZXJ2ZXJFcnJvci5UT0tFTl9FWFBJUkVEXTogQXV0aEVycm9yQ29kZS5UT0tFTl9FWFBJUkVELFxuICBbU2VydmVyRXJyb3IuVVNFUl9OT1RfRk9VTkRdOiBBdXRoRXJyb3JDb2RlLlRPS0VOX0VYUElSRUQsXG5cbiAgLy8gT3RoZXIgZXJyb3JzLlxuICBbU2VydmVyRXJyb3IuVE9PX01BTllfQVRURU1QVFNfVFJZX0xBVEVSXTpcbiAgICBBdXRoRXJyb3JDb2RlLlRPT19NQU5ZX0FUVEVNUFRTX1RSWV9MQVRFUixcbiAgW1NlcnZlckVycm9yLlBBU1NXT1JEX0RPRVNfTk9UX01FRVRfUkVRVUlSRU1FTlRTXTpcbiAgICBBdXRoRXJyb3JDb2RlLlBBU1NXT1JEX0RPRVNfTk9UX01FRVRfUkVRVUlSRU1FTlRTLFxuXG4gIC8vIFBob25lIEF1dGggcmVsYXRlZCBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX0NPREVdOiBBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09ERSxcbiAgW1NlcnZlckVycm9yLklOVkFMSURfU0VTU0lPTl9JTkZPXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX1NFU1NJT05fSU5GTyxcbiAgW1NlcnZlckVycm9yLklOVkFMSURfVEVNUE9SQVJZX1BST09GXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX0NSRURFTlRJQUwsXG4gIFtTZXJ2ZXJFcnJvci5NSVNTSU5HX1NFU1NJT05fSU5GT106IEF1dGhFcnJvckNvZGUuTUlTU0lOR19TRVNTSU9OX0lORk8sXG4gIFtTZXJ2ZXJFcnJvci5TRVNTSU9OX0VYUElSRURdOiBBdXRoRXJyb3JDb2RlLkNPREVfRVhQSVJFRCxcblxuICAvLyBPdGhlciBhY3Rpb24gY29kZSBlcnJvcnMgd2hlbiBhZGRpdGlvbmFsIHNldHRpbmdzIHBhc3NlZC5cbiAgLy8gTUlTU0lOR19DT05USU5VRV9VUkkgaXMgZ2V0dGluZyBtYXBwZWQgdG8gSU5URVJOQUxfRVJST1IgYWJvdmUuXG4gIC8vIFRoaXMgaXMgT0sgYXMgdGhpcyBlcnJvciB3aWxsIGJlIGNhdWdodCBieSBjbGllbnQgc2lkZSB2YWxpZGF0aW9uLlxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19BTkRST0lEX1BBQ0tBR0VfTkFNRV06XG4gICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX0FORFJPSURfUEFDS0FHRV9OQU1FLFxuICBbU2VydmVyRXJyb3IuVU5BVVRIT1JJWkVEX0RPTUFJTl06IEF1dGhFcnJvckNvZGUuVU5BVVRIT1JJWkVEX0RPTUFJTixcblxuICAvLyBnZXRQcm9qZWN0Q29uZmlnIGVycm9ycyB3aGVuIGNsaWVudElkIGlzIHBhc3NlZC5cbiAgW1NlcnZlckVycm9yLklOVkFMSURfT0FVVEhfQ0xJRU5UX0lEXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX09BVVRIX0NMSUVOVF9JRCxcblxuICAvLyBVc2VyIGFjdGlvbnMgKHNpZ24tdXAgb3IgZGVsZXRpb24pIGRpc2FibGVkIGVycm9ycy5cbiAgW1NlcnZlckVycm9yLkFETUlOX09OTFlfT1BFUkFUSU9OXTogQXV0aEVycm9yQ29kZS5BRE1JTl9PTkxZX09QRVJBVElPTixcblxuICAvLyBNdWx0aSBmYWN0b3IgcmVsYXRlZCBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5JTlZBTElEX01GQV9QRU5ESU5HX0NSRURFTlRJQUxdOlxuICAgIEF1dGhFcnJvckNvZGUuSU5WQUxJRF9NRkFfU0VTU0lPTixcbiAgW1NlcnZlckVycm9yLk1GQV9FTlJPTExNRU5UX05PVF9GT1VORF06IEF1dGhFcnJvckNvZGUuTUZBX0lORk9fTk9UX0ZPVU5ELFxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19NRkFfRU5ST0xMTUVOVF9JRF06IEF1dGhFcnJvckNvZGUuTUlTU0lOR19NRkFfSU5GTyxcbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfTUZBX1BFTkRJTkdfQ1JFREVOVElBTF06XG4gICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX01GQV9TRVNTSU9OLFxuICBbU2VydmVyRXJyb3IuU0VDT05EX0ZBQ1RPUl9FWElTVFNdOlxuICAgIEF1dGhFcnJvckNvZGUuU0VDT05EX0ZBQ1RPUl9BTFJFQURZX0VOUk9MTEVELFxuICBbU2VydmVyRXJyb3IuU0VDT05EX0ZBQ1RPUl9MSU1JVF9FWENFRURFRF06XG4gICAgQXV0aEVycm9yQ29kZS5TRUNPTkRfRkFDVE9SX0xJTUlUX0VYQ0VFREVELFxuXG4gIC8vIEJsb2NraW5nIGZ1bmN0aW9ucyByZWxhdGVkIGVycm9ycy5cbiAgW1NlcnZlckVycm9yLkJMT0NLSU5HX0ZVTkNUSU9OX0VSUk9SX1JFU1BPTlNFXTogQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUixcblxuICAvLyBSZWNhcHRjaGEgcmVsYXRlZCBlcnJvcnMuXG4gIFtTZXJ2ZXJFcnJvci5SRUNBUFRDSEFfTk9UX0VOQUJMRURdOiBBdXRoRXJyb3JDb2RlLlJFQ0FQVENIQV9OT1RfRU5BQkxFRCxcbiAgW1NlcnZlckVycm9yLk1JU1NJTkdfUkVDQVBUQ0hBX1RPS0VOXTogQXV0aEVycm9yQ29kZS5NSVNTSU5HX1JFQ0FQVENIQV9UT0tFTixcbiAgW1NlcnZlckVycm9yLklOVkFMSURfUkVDQVBUQ0hBX1RPS0VOXTogQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0FQVENIQV9UT0tFTixcbiAgW1NlcnZlckVycm9yLklOVkFMSURfUkVDQVBUQ0hBX0FDVElPTl06XG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0FQVENIQV9BQ1RJT04sXG4gIFtTZXJ2ZXJFcnJvci5NSVNTSU5HX0NMSUVOVF9UWVBFXTogQXV0aEVycm9yQ29kZS5NSVNTSU5HX0NMSUVOVF9UWVBFLFxuICBbU2VydmVyRXJyb3IuTUlTU0lOR19SRUNBUFRDSEFfVkVSU0lPTl06XG4gICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX1JFQ0FQVENIQV9WRVJTSU9OLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9SRUNBUFRDSEFfVkVSU0lPTl06XG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX1JFQ0FQVENIQV9WRVJTSU9OLFxuICBbU2VydmVyRXJyb3IuSU5WQUxJRF9SRVFfVFlQRV06IEF1dGhFcnJvckNvZGUuSU5WQUxJRF9SRVFfVFlQRVxufTtcbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBGaXJlYmFzZUVycm9yLFxuICBpc0Nsb3VkZmxhcmVXb3JrZXIsXG4gIGlzQ2xvdWRXb3Jrc3RhdGlvbixcbiAgcXVlcnlzdHJpbmdcbn0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlLCBOYW1lZEVycm9yUGFyYW1zIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgX2NyZWF0ZUVycm9yLFxuICBfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZSxcbiAgX2ZhaWxcbn0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBEZWxheSB9IGZyb20gJy4uL2NvcmUvdXRpbC9kZWxheSc7XG5pbXBvcnQgeyBfZW11bGF0b3JVcmwgfSBmcm9tICcuLi9jb3JlL3V0aWwvZW11bGF0b3InO1xuaW1wb3J0IHsgRmV0Y2hQcm92aWRlciB9IGZyb20gJy4uL2NvcmUvdXRpbC9mZXRjaF9wcm92aWRlcic7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCwgQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSwgVGFnZ2VkV2l0aFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBJZFRva2VuTWZhUmVzcG9uc2UgfSBmcm9tICcuL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBTRVJWRVJfRVJST1JfTUFQLCBTZXJ2ZXJFcnJvciwgU2VydmVyRXJyb3JNYXAgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBQZXJzaXN0ZW5jZVR5cGUgfSBmcm9tICcuLi9jb3JlL3BlcnNpc3RlbmNlJztcbmltcG9ydCB7IENvb2tpZVBlcnNpc3RlbmNlIH0gZnJvbSAnLi4vcGxhdGZvcm1fYnJvd3Nlci9wZXJzaXN0ZW5jZS9jb29raWVfc3RvcmFnZSc7XG5cbmV4cG9ydCBjb25zdCBlbnVtIEh0dHBNZXRob2Qge1xuICBQT1NUID0gJ1BPU1QnLFxuICBHRVQgPSAnR0VUJ1xufVxuXG5leHBvcnQgY29uc3QgZW51bSBIdHRwSGVhZGVyIHtcbiAgQ09OVEVOVF9UWVBFID0gJ0NvbnRlbnQtVHlwZScsXG4gIFhfRklSRUJBU0VfTE9DQUxFID0gJ1gtRmlyZWJhc2UtTG9jYWxlJyxcbiAgWF9DTElFTlRfVkVSU0lPTiA9ICdYLUNsaWVudC1WZXJzaW9uJyxcbiAgWF9GSVJFQkFTRV9HTVBJRCA9ICdYLUZpcmViYXNlLWdtcGlkJyxcbiAgWF9GSVJFQkFTRV9DTElFTlQgPSAnWC1GaXJlYmFzZS1DbGllbnQnLFxuICBYX0ZJUkVCQVNFX0FQUF9DSEVDSyA9ICdYLUZpcmViYXNlLUFwcENoZWNrJ1xufVxuXG5leHBvcnQgY29uc3QgZW51bSBFbmRwb2ludCB7XG4gIENSRUFURV9BVVRIX1VSSSA9ICcvdjEvYWNjb3VudHM6Y3JlYXRlQXV0aFVyaScsXG4gIERFTEVURV9BQ0NPVU5UID0gJy92MS9hY2NvdW50czpkZWxldGUnLFxuICBSRVNFVF9QQVNTV09SRCA9ICcvdjEvYWNjb3VudHM6cmVzZXRQYXNzd29yZCcsXG4gIFNJR05fVVAgPSAnL3YxL2FjY291bnRzOnNpZ25VcCcsXG4gIFNJR05fSU5fV0lUSF9DVVNUT01fVE9LRU4gPSAnL3YxL2FjY291bnRzOnNpZ25JbldpdGhDdXN0b21Ub2tlbicsXG4gIFNJR05fSU5fV0lUSF9FTUFJTF9MSU5LID0gJy92MS9hY2NvdW50czpzaWduSW5XaXRoRW1haWxMaW5rJyxcbiAgU0lHTl9JTl9XSVRIX0lEUCA9ICcvdjEvYWNjb3VudHM6c2lnbkluV2l0aElkcCcsXG4gIFNJR05fSU5fV0lUSF9QQVNTV09SRCA9ICcvdjEvYWNjb3VudHM6c2lnbkluV2l0aFBhc3N3b3JkJyxcbiAgU0lHTl9JTl9XSVRIX1BIT05FX05VTUJFUiA9ICcvdjEvYWNjb3VudHM6c2lnbkluV2l0aFBob25lTnVtYmVyJyxcbiAgU0VORF9WRVJJRklDQVRJT05fQ09ERSA9ICcvdjEvYWNjb3VudHM6c2VuZFZlcmlmaWNhdGlvbkNvZGUnLFxuICBTRU5EX09PQl9DT0RFID0gJy92MS9hY2NvdW50czpzZW5kT29iQ29kZScsXG4gIFNFVF9BQ0NPVU5UX0lORk8gPSAnL3YxL2FjY291bnRzOnVwZGF0ZScsXG4gIEdFVF9BQ0NPVU5UX0lORk8gPSAnL3YxL2FjY291bnRzOmxvb2t1cCcsXG4gIEdFVF9SRUNBUFRDSEFfUEFSQU0gPSAnL3YxL3JlY2FwdGNoYVBhcmFtcycsXG4gIFNUQVJUX01GQV9FTlJPTExNRU5UID0gJy92Mi9hY2NvdW50cy9tZmFFbnJvbGxtZW50OnN0YXJ0JyxcbiAgRklOQUxJWkVfTUZBX0VOUk9MTE1FTlQgPSAnL3YyL2FjY291bnRzL21mYUVucm9sbG1lbnQ6ZmluYWxpemUnLFxuICBTVEFSVF9NRkFfU0lHTl9JTiA9ICcvdjIvYWNjb3VudHMvbWZhU2lnbkluOnN0YXJ0JyxcbiAgRklOQUxJWkVfTUZBX1NJR05fSU4gPSAnL3YyL2FjY291bnRzL21mYVNpZ25JbjpmaW5hbGl6ZScsXG4gIFdJVEhEUkFXX01GQSA9ICcvdjIvYWNjb3VudHMvbWZhRW5yb2xsbWVudDp3aXRoZHJhdycsXG4gIEdFVF9QUk9KRUNUX0NPTkZJRyA9ICcvdjEvcHJvamVjdHMnLFxuICBHRVRfUkVDQVBUQ0hBX0NPTkZJRyA9ICcvdjIvcmVjYXB0Y2hhQ29uZmlnJyxcbiAgR0VUX1BBU1NXT1JEX1BPTElDWSA9ICcvdjIvcGFzc3dvcmRQb2xpY3knLFxuICBUT0tFTiA9ICcvdjEvdG9rZW4nLFxuICBSRVZPS0VfVE9LRU4gPSAnL3YyL2FjY291bnRzOnJldm9rZVRva2VuJ1xufVxuXG5jb25zdCBDb29raWVBdXRoUHJveGllZEVuZHBvaW50czogc3RyaW5nW10gPSBbXG4gIEVuZHBvaW50LlNJR05fSU5fV0lUSF9DVVNUT01fVE9LRU4sXG4gIEVuZHBvaW50LlNJR05fSU5fV0lUSF9FTUFJTF9MSU5LLFxuICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfSURQLFxuICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfUEFTU1dPUkQsXG4gIEVuZHBvaW50LlNJR05fSU5fV0lUSF9QSE9ORV9OVU1CRVIsXG4gIEVuZHBvaW50LlRPS0VOXG5dO1xuXG5leHBvcnQgY29uc3QgZW51bSBSZWNhcHRjaGFDbGllbnRUeXBlIHtcbiAgV0VCID0gJ0NMSUVOVF9UWVBFX1dFQicsXG4gIEFORFJPSUQgPSAnQ0xJRU5UX1RZUEVfQU5EUk9JRCcsXG4gIElPUyA9ICdDTElFTlRfVFlQRV9JT1MnXG59XG5cbmV4cG9ydCBjb25zdCBlbnVtIFJlY2FwdGNoYVZlcnNpb24ge1xuICBFTlRFUlBSSVNFID0gJ1JFQ0FQVENIQV9FTlRFUlBSSVNFJ1xufVxuXG5leHBvcnQgY29uc3QgZW51bSBSZWNhcHRjaGFBY3Rpb25OYW1lIHtcbiAgU0lHTl9JTl9XSVRIX1BBU1NXT1JEID0gJ3NpZ25JbldpdGhQYXNzd29yZCcsXG4gIEdFVF9PT0JfQ09ERSA9ICdnZXRPb2JDb2RlJyxcbiAgU0lHTl9VUF9QQVNTV09SRCA9ICdzaWduVXBQYXNzd29yZCcsXG4gIFNFTkRfVkVSSUZJQ0FUSU9OX0NPREUgPSAnc2VuZFZlcmlmaWNhdGlvbkNvZGUnLFxuICBNRkFfU01TX0VOUk9MTE1FTlQgPSAnbWZhU21zRW5yb2xsbWVudCcsXG4gIE1GQV9TTVNfU0lHTklOID0gJ21mYVNtc1NpZ25Jbidcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gRW5mb3JjZW1lbnRTdGF0ZSB7XG4gIEVORk9SQ0UgPSAnRU5GT1JDRScsXG4gIEFVRElUID0gJ0FVRElUJyxcbiAgT0ZGID0gJ09GRicsXG4gIEVORk9SQ0VNRU5UX1NUQVRFX1VOU1BFQ0lGSUVEID0gJ0VORk9SQ0VNRU5UX1NUQVRFX1VOU1BFQ0lGSUVEJ1xufVxuXG4vLyBQcm92aWRlcnMgdGhhdCBoYXZlIHJlQ0FQVENIQSBFbnRlcnByaXNlIHN1cHBvcnQuXG5leHBvcnQgY29uc3QgZW51bSBSZWNhcHRjaGFBdXRoUHJvdmlkZXIge1xuICBFTUFJTF9QQVNTV09SRF9QUk9WSURFUiA9ICdFTUFJTF9QQVNTV09SRF9QUk9WSURFUicsXG4gIFBIT05FX1BST1ZJREVSID0gJ1BIT05FX1BST1ZJREVSJ1xufVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9BUElfVElNRU9VVF9NUyA9IG5ldyBEZWxheSgzMF8wMDAsIDYwXzAwMCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBfYWRkVGlkSWZOZWNlc3Nhcnk8VCBleHRlbmRzIHsgdGVuYW50SWQ/OiBzdHJpbmcgfT4oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFRcbik6IFQge1xuICBpZiAoYXV0aC50ZW5hbnRJZCAmJiAhcmVxdWVzdC50ZW5hbnRJZCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5yZXF1ZXN0LFxuICAgICAgdGVuYW50SWQ6IGF1dGgudGVuYW50SWRcbiAgICB9O1xuICB9XG4gIHJldHVybiByZXF1ZXN0O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX3BlcmZvcm1BcGlSZXF1ZXN0PFQsIFY+KFxuICBhdXRoOiBBdXRoLFxuICBtZXRob2Q6IEh0dHBNZXRob2QsXG4gIHBhdGg6IEVuZHBvaW50LFxuICByZXF1ZXN0PzogVCxcbiAgY3VzdG9tRXJyb3JNYXA6IFBhcnRpYWw8U2VydmVyRXJyb3JNYXA8U2VydmVyRXJyb3I+PiA9IHt9XG4pOiBQcm9taXNlPFY+IHtcbiAgcmV0dXJuIF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZyhhdXRoLCBjdXN0b21FcnJvck1hcCwgYXN5bmMgKCkgPT4ge1xuICAgIGxldCBib2R5ID0ge307XG4gICAgbGV0IHBhcmFtcyA9IHt9O1xuICAgIGlmIChyZXF1ZXN0KSB7XG4gICAgICBpZiAobWV0aG9kID09PSBIdHRwTWV0aG9kLkdFVCkge1xuICAgICAgICBwYXJhbXMgPSByZXF1ZXN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYm9keSA9IHtcbiAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShyZXF1ZXN0KVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5ID0gcXVlcnlzdHJpbmcoe1xuICAgICAga2V5OiBhdXRoLmNvbmZpZy5hcGlLZXksXG4gICAgICAuLi5wYXJhbXNcbiAgICB9KS5zbGljZSgxKTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSBhd2FpdCAoYXV0aCBhcyBBdXRoSW50ZXJuYWwpLl9nZXRBZGRpdGlvbmFsSGVhZGVycygpO1xuICAgIGhlYWRlcnNbSHR0cEhlYWRlci5DT05URU5UX1RZUEVdID0gJ2FwcGxpY2F0aW9uL2pzb24nO1xuXG4gICAgaWYgKGF1dGgubGFuZ3VhZ2VDb2RlKSB7XG4gICAgICBoZWFkZXJzW0h0dHBIZWFkZXIuWF9GSVJFQkFTRV9MT0NBTEVdID0gYXV0aC5sYW5ndWFnZUNvZGU7XG4gICAgfVxuXG4gICAgY29uc3QgZmV0Y2hBcmdzOiBSZXF1ZXN0SW5pdCA9IHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIGhlYWRlcnMsXG4gICAgICAuLi5ib2R5XG4gICAgfTtcblxuICAgIC8qIFNlY3VyaXR5LWNvbnNjaW91cyBzZXJ2ZXItc2lkZSBmcmFtZXdvcmtzIHRlbmQgdG8gaGF2ZSBidWlsdCBpbiBtaXRpZ2F0aW9ucyBmb3IgcmVmZXJyZXJcbiAgICAgICBwcm9ibGVtc1wiLiBTZWUgdGhlIENsb3VkZmxhcmUgR2l0SHViIGlzc3VlICM0ODc6IEVycm9yOiBUaGUgJ3JlZmVycmVyUG9saWN5JyBmaWVsZCBvblxuICAgICAgICdSZXF1ZXN0SW5pdGlhbGl6ZXJEaWN0JyBpcyBub3QgaW1wbGVtZW50ZWQuXCJcbiAgICAgICBodHRwczovL2dpdGh1Yi5jb20vY2xvdWRmbGFyZS9uZXh0LW9uLXBhZ2VzL2lzc3Vlcy80ODcgKi9cbiAgICBpZiAoIWlzQ2xvdWRmbGFyZVdvcmtlcigpKSB7XG4gICAgICBmZXRjaEFyZ3MucmVmZXJyZXJQb2xpY3kgPSAnbm8tcmVmZXJyZXInO1xuICAgIH1cblxuICAgIGlmIChhdXRoLmVtdWxhdG9yQ29uZmlnICYmIGlzQ2xvdWRXb3Jrc3RhdGlvbihhdXRoLmVtdWxhdG9yQ29uZmlnLmhvc3QpKSB7XG4gICAgICBmZXRjaEFyZ3MuY3JlZGVudGlhbHMgPSAnaW5jbHVkZSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIEZldGNoUHJvdmlkZXIuZmV0Y2goKShcbiAgICAgIGF3YWl0IF9nZXRGaW5hbFRhcmdldChhdXRoLCBhdXRoLmNvbmZpZy5hcGlIb3N0LCBwYXRoLCBxdWVyeSksXG4gICAgICBmZXRjaEFyZ3NcbiAgICApO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZzxWPihcbiAgYXV0aDogQXV0aCxcbiAgY3VzdG9tRXJyb3JNYXA6IFBhcnRpYWw8U2VydmVyRXJyb3JNYXA8U2VydmVyRXJyb3I+PixcbiAgZmV0Y2hGbjogKCkgPT4gUHJvbWlzZTxSZXNwb25zZT5cbik6IFByb21pc2U8Vj4ge1xuICAoYXV0aCBhcyBBdXRoSW50ZXJuYWwpLl9jYW5Jbml0RW11bGF0b3IgPSBmYWxzZTtcbiAgY29uc3QgZXJyb3JNYXAgPSB7IC4uLlNFUlZFUl9FUlJPUl9NQVAsIC4uLmN1c3RvbUVycm9yTWFwIH07XG4gIHRyeSB7XG4gICAgY29uc3QgbmV0d29ya1RpbWVvdXQgPSBuZXcgTmV0d29ya1RpbWVvdXQ8UmVzcG9uc2U+KGF1dGgpO1xuICAgIGNvbnN0IHJlc3BvbnNlOiBSZXNwb25zZSA9IGF3YWl0IFByb21pc2UucmFjZTxQcm9taXNlPFJlc3BvbnNlPj4oW1xuICAgICAgZmV0Y2hGbigpLFxuICAgICAgbmV0d29ya1RpbWVvdXQucHJvbWlzZVxuICAgIF0pO1xuXG4gICAgLy8gSWYgd2UndmUgcmVhY2hlZCB0aGlzIHBvaW50LCB0aGUgZmV0Y2ggc3VjY2VlZGVkIGFuZCB0aGUgbmV0d29ya1RpbWVvdXRcbiAgICAvLyBkaWRuJ3QgdGhyb3c7IGNsZWFyIHRoZSBuZXR3b3JrIHRpbWVvdXQgZGVsYXkgc28gdGhhdCBOb2RlIHdvbid0IGhhbmdcbiAgICBuZXR3b3JrVGltZW91dC5jbGVhck5ldHdvcmtUaW1lb3V0KCk7XG5cbiAgICBjb25zdCBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIGlmICgnbmVlZENvbmZpcm1hdGlvbicgaW4ganNvbikge1xuICAgICAgdGhyb3cgX21ha2VUYWdnZWRFcnJvcihhdXRoLCBBdXRoRXJyb3JDb2RlLk5FRURfQ09ORklSTUFUSU9OLCBqc29uKTtcbiAgICB9XG5cbiAgICBpZiAocmVzcG9uc2Uub2sgJiYgISgnZXJyb3JNZXNzYWdlJyBpbiBqc29uKSkge1xuICAgICAgcmV0dXJuIGpzb247XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IHJlc3BvbnNlLm9rID8ganNvbi5lcnJvck1lc3NhZ2UgOiBqc29uLmVycm9yLm1lc3NhZ2U7XG4gICAgICBjb25zdCBbc2VydmVyRXJyb3JDb2RlLCBzZXJ2ZXJFcnJvck1lc3NhZ2VdID0gZXJyb3JNZXNzYWdlLnNwbGl0KCcgOiAnKTtcbiAgICAgIGlmIChzZXJ2ZXJFcnJvckNvZGUgPT09IFNlcnZlckVycm9yLkZFREVSQVRFRF9VU0VSX0lEX0FMUkVBRFlfTElOS0VEKSB7XG4gICAgICAgIHRocm93IF9tYWtlVGFnZ2VkRXJyb3IoXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICBBdXRoRXJyb3JDb2RlLkNSRURFTlRJQUxfQUxSRUFEWV9JTl9VU0UsXG4gICAgICAgICAganNvblxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChzZXJ2ZXJFcnJvckNvZGUgPT09IFNlcnZlckVycm9yLkVNQUlMX0VYSVNUUykge1xuICAgICAgICB0aHJvdyBfbWFrZVRhZ2dlZEVycm9yKGF1dGgsIEF1dGhFcnJvckNvZGUuRU1BSUxfRVhJU1RTLCBqc29uKTtcbiAgICAgIH0gZWxzZSBpZiAoc2VydmVyRXJyb3JDb2RlID09PSBTZXJ2ZXJFcnJvci5VU0VSX0RJU0FCTEVEKSB7XG4gICAgICAgIHRocm93IF9tYWtlVGFnZ2VkRXJyb3IoYXV0aCwgQXV0aEVycm9yQ29kZS5VU0VSX0RJU0FCTEVELCBqc29uKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGF1dGhFcnJvciA9XG4gICAgICAgIGVycm9yTWFwW3NlcnZlckVycm9yQ29kZSBhcyBTZXJ2ZXJFcnJvcl0gfHxcbiAgICAgICAgKHNlcnZlckVycm9yQ29kZVxuICAgICAgICAgIC50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgLnJlcGxhY2UoL1tfXFxzXSsvZywgJy0nKSBhcyB1bmtub3duIGFzIEF1dGhFcnJvckNvZGUpO1xuICAgICAgaWYgKHNlcnZlckVycm9yTWVzc2FnZSkge1xuICAgICAgICB0aHJvdyBfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZShhdXRoLCBhdXRoRXJyb3IsIHNlcnZlckVycm9yTWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfZmFpbChhdXRoLCBhdXRoRXJyb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgRmlyZWJhc2VFcnJvcikge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgLy8gQ2hhbmdpbmcgdGhpcyB0byBhIGRpZmZlcmVudCBlcnJvciBjb2RlIHdpbGwgbG9nIHVzZXIgb3V0IHdoZW4gdGhlcmUgaXMgYSBuZXR3b3JrIGVycm9yXG4gICAgLy8gYmVjYXVzZSB3ZSB0cmVhdCBhbnkgZXJyb3Igb3RoZXIgdGhhbiBORVRXT1JLX1JFUVVFU1RfRkFJTEVEIGFzIHRva2VuIGlzIGludmFsaWQuXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2ZpcmViYXNlL2ZpcmViYXNlLWpzLXNkay9ibG9iLzRmYmM3MzYxMGQ3MGJlNGUwODUyZTdkZTYzYTM5Y2I3ODk3ZTg1NDYvcGFja2FnZXMvYXV0aC9zcmMvY29yZS9hdXRoL2F1dGhfaW1wbC50cyNMMzA5LUwzMTZcbiAgICBfZmFpbChhdXRoLCBBdXRoRXJyb3JDb2RlLk5FVFdPUktfUkVRVUVTVF9GQUlMRUQsIHsgJ21lc3NhZ2UnOiBTdHJpbmcoZSkgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9wZXJmb3JtU2lnbkluUmVxdWVzdDxULCBWIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlPihcbiAgYXV0aDogQXV0aCxcbiAgbWV0aG9kOiBIdHRwTWV0aG9kLFxuICBwYXRoOiBFbmRwb2ludCxcbiAgcmVxdWVzdD86IFQsXG4gIGN1c3RvbUVycm9yTWFwOiBQYXJ0aWFsPFNlcnZlckVycm9yTWFwPFNlcnZlckVycm9yPj4gPSB7fVxuKTogUHJvbWlzZTxWPiB7XG4gIGNvbnN0IHNlcnZlclJlc3BvbnNlID0gYXdhaXQgX3BlcmZvcm1BcGlSZXF1ZXN0PFQsIFYgfCBJZFRva2VuTWZhUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgbWV0aG9kLFxuICAgIHBhdGgsXG4gICAgcmVxdWVzdCxcbiAgICBjdXN0b21FcnJvck1hcFxuICApO1xuICBpZiAoJ21mYVBlbmRpbmdDcmVkZW50aWFsJyBpbiBzZXJ2ZXJSZXNwb25zZSkge1xuICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuTUZBX1JFUVVJUkVELCB7XG4gICAgICBfc2VydmVyUmVzcG9uc2U6IHNlcnZlclJlc3BvbnNlXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc2VydmVyUmVzcG9uc2UgYXMgVjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9nZXRGaW5hbFRhcmdldChcbiAgYXV0aDogQXV0aCxcbiAgaG9zdDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIHF1ZXJ5OiBzdHJpbmdcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGJhc2UgPSBgJHtob3N0fSR7cGF0aH0/JHtxdWVyeX1gO1xuXG4gIGNvbnN0IGF1dGhJbnRlcm5hbCA9IGF1dGggYXMgQXV0aEludGVybmFsO1xuICBjb25zdCBmaW5hbFRhcmdldCA9IGF1dGhJbnRlcm5hbC5jb25maWcuZW11bGF0b3JcbiAgICA/IF9lbXVsYXRvclVybChhdXRoLmNvbmZpZyBhcyBDb25maWdJbnRlcm5hbCwgYmFzZSlcbiAgICA6IGAke2F1dGguY29uZmlnLmFwaVNjaGVtZX06Ly8ke2Jhc2V9YDtcblxuICAvLyBDb29raWUgYXV0aCB3b3JrcyBieSBNaVRNaW5nIHRoZSBzaWduSW4gYW5kIHRva2VuIGVuZHBvaW50cyBmcm9tIHRoZSBkZXZlbG9wZXIncyBiYWNrZW5kLFxuICAvLyBzYXZpbmcgdGhlIGlkVG9rZW4gYW5kIHJlZnJlc2hUb2tlbiBpbnRvIGNvb2tpZXMsIGFuZCB0aGVuIHJlZGFjdGluZyB0aGUgcmVmcmVzaFRva2VuXG4gIC8vIGZyb20gdGhlIHJlc3BvbnNlXG4gIGlmIChDb29raWVBdXRoUHJveGllZEVuZHBvaW50cy5pbmNsdWRlcyhwYXRoKSkge1xuICAgIC8vIFBlcnNpc3RlbmNlIG1hbmFnZXIgaXMgYXN5bmMsIHdlIG5lZWQgdG8gYXdhaXQgaXQuIFdlIGNhbid0IGp1c3Qgd2FpdCBmb3IgYXV0aCBpbml0aWFsaXplZFxuICAgIC8vIGhlcmUgc2luY2UgYXV0aCBpbml0aWFsaXphdGlvbiBjYWxscyB0aGlzIGZ1bmN0aW9uLlxuICAgIGF3YWl0IGF1dGhJbnRlcm5hbC5fcGVyc2lzdGVuY2VNYW5hZ2VyQXZhaWxhYmxlO1xuICAgIGlmIChhdXRoSW50ZXJuYWwuX2dldFBlcnNpc3RlbmNlVHlwZSgpID09PSBQZXJzaXN0ZW5jZVR5cGUuQ09PS0lFKSB7XG4gICAgICBjb25zdCBjb29raWVQZXJzaXN0ZW5jZSA9XG4gICAgICAgIGF1dGhJbnRlcm5hbC5fZ2V0UGVyc2lzdGVuY2UoKSBhcyBDb29raWVQZXJzaXN0ZW5jZTtcbiAgICAgIHJldHVybiBjb29raWVQZXJzaXN0ZW5jZS5fZ2V0RmluYWxUYXJnZXQoZmluYWxUYXJnZXQpLnRvU3RyaW5nKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZpbmFsVGFyZ2V0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3BhcnNlRW5mb3JjZW1lbnRTdGF0ZShcbiAgZW5mb3JjZW1lbnRTdGF0ZVN0cjogc3RyaW5nXG4pOiBFbmZvcmNlbWVudFN0YXRlIHtcbiAgc3dpdGNoIChlbmZvcmNlbWVudFN0YXRlU3RyKSB7XG4gICAgY2FzZSAnRU5GT1JDRSc6XG4gICAgICByZXR1cm4gRW5mb3JjZW1lbnRTdGF0ZS5FTkZPUkNFO1xuICAgIGNhc2UgJ0FVRElUJzpcbiAgICAgIHJldHVybiBFbmZvcmNlbWVudFN0YXRlLkFVRElUO1xuICAgIGNhc2UgJ09GRic6XG4gICAgICByZXR1cm4gRW5mb3JjZW1lbnRTdGF0ZS5PRkY7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBFbmZvcmNlbWVudFN0YXRlLkVORk9SQ0VNRU5UX1NUQVRFX1VOU1BFQ0lGSUVEO1xuICB9XG59XG5cbmNsYXNzIE5ldHdvcmtUaW1lb3V0PFQ+IHtcbiAgLy8gTm9kZSB0aW1lcnMgYW5kIGJyb3dzZXIgdGltZXJzIGFyZSBmdW5kYW1lbnRhbGx5IGluY29tcGF0aWJsZSwgYnV0IHdlXG4gIC8vIGRvbid0IGNhcmUgYWJvdXQgdGhlIHZhbHVlIGhlcmVcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgcHJpdmF0ZSB0aW1lcjogYW55IHwgbnVsbCA9IG51bGw7XG4gIHJlYWRvbmx5IHByb21pc2UgPSBuZXcgUHJvbWlzZTxUPigoXywgcmVqZWN0KSA9PiB7XG4gICAgdGhpcy50aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgcmV0dXJuIHJlamVjdChcbiAgICAgICAgX2NyZWF0ZUVycm9yKHRoaXMuYXV0aCwgQXV0aEVycm9yQ29kZS5ORVRXT1JLX1JFUVVFU1RfRkFJTEVEKVxuICAgICAgKTtcbiAgICB9LCBERUZBVUxUX0FQSV9USU1FT1VUX01TLmdldCgpKTtcbiAgfSk7XG5cbiAgY2xlYXJOZXR3b3JrVGltZW91dCgpOiB2b2lkIHtcbiAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGgpIHt9XG59XG5cbmludGVyZmFjZSBQb3RlbnRpYWxSZXNwb25zZSBleHRlbmRzIElkVG9rZW5SZXNwb25zZSB7XG4gIGVtYWlsPzogc3RyaW5nO1xuICBwaG9uZU51bWJlcj86IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9tYWtlVGFnZ2VkRXJyb3IoXG4gIGF1dGg6IEF1dGgsXG4gIGNvZGU6IEF1dGhFcnJvckNvZGUsXG4gIHJlc3BvbnNlOiBQb3RlbnRpYWxSZXNwb25zZVxuKTogRmlyZWJhc2VFcnJvciB7XG4gIGNvbnN0IGVycm9yUGFyYW1zOiBOYW1lZEVycm9yUGFyYW1zID0ge1xuICAgIGFwcE5hbWU6IGF1dGgubmFtZVxuICB9O1xuXG4gIGlmIChyZXNwb25zZS5lbWFpbCkge1xuICAgIGVycm9yUGFyYW1zLmVtYWlsID0gcmVzcG9uc2UuZW1haWw7XG4gIH1cbiAgaWYgKHJlc3BvbnNlLnBob25lTnVtYmVyKSB7XG4gICAgZXJyb3JQYXJhbXMucGhvbmVOdW1iZXIgPSByZXNwb25zZS5waG9uZU51bWJlcjtcbiAgfVxuXG4gIGNvbnN0IGVycm9yID0gX2NyZWF0ZUVycm9yKGF1dGgsIGNvZGUsIGVycm9yUGFyYW1zKTtcblxuICAvLyBXZSBrbm93IGN1c3RvbURhdGEgaXMgZGVmaW5lZCBvbiBlcnJvciBiZWNhdXNlIGVycm9yUGFyYW1zIGlzIGRlZmluZWRcbiAgKGVycm9yLmN1c3RvbURhdGEhIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlKS5fdG9rZW5SZXNwb25zZSA9IHJlc3BvbnNlO1xuICByZXR1cm4gZXJyb3I7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUmVjYXB0Y2hhUGFyYW1ldGVycyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQge1xuICBHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZSxcbiAgUmVjYXB0Y2hhRW5mb3JjZW1lbnRQcm92aWRlclN0YXRlXG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9yZWNhcHRjaGEnO1xuaW1wb3J0IHtcbiAgRW5mb3JjZW1lbnRTdGF0ZSxcbiAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyLFxuICBfcGFyc2VFbmZvcmNlbWVudFN0YXRlXG59IGZyb20gJy4uLy4uL2FwaS9pbmRleCc7XG5cbi8vIHJlQ0FQVENIQSB2MiBpbnRlcmZhY2VcbmV4cG9ydCBpbnRlcmZhY2UgUmVjYXB0Y2hhIHtcbiAgcmVuZGVyOiAoY29udGFpbmVyOiBIVE1MRWxlbWVudCwgcGFyYW1ldGVyczogUmVjYXB0Y2hhUGFyYW1ldGVycykgPT4gbnVtYmVyO1xuICBnZXRSZXNwb25zZTogKGlkOiBudW1iZXIpID0+IHN0cmluZztcbiAgZXhlY3V0ZTogKGlkOiBudW1iZXIpID0+IHVua25vd247XG4gIHJlc2V0OiAoaWQ6IG51bWJlcikgPT4gdW5rbm93bjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVjIoXG4gIGdyZWNhcHRjaGE6IFJlY2FwdGNoYSB8IEdyZUNBUFRDSEEgfCB1bmRlZmluZWRcbik6IGdyZWNhcHRjaGEgaXMgUmVjYXB0Y2hhIHtcbiAgcmV0dXJuIChcbiAgICBncmVjYXB0Y2hhICE9PSB1bmRlZmluZWQgJiZcbiAgICAoZ3JlY2FwdGNoYSBhcyBSZWNhcHRjaGEpLmdldFJlc3BvbnNlICE9PSB1bmRlZmluZWRcbiAgKTtcbn1cblxuLy8gcmVDQVBUQ0hBIEVudGVycHJpc2UgJiB2MyBzaGFyZWQgaW50ZXJmYWNlXG5leHBvcnQgaW50ZXJmYWNlIEdyZUNBUFRDSEFUb3BMZXZlbCBleHRlbmRzIEdyZUNBUFRDSEEge1xuICBlbnRlcnByaXNlOiBHcmVDQVBUQ0hBO1xufVxuXG4vLyByZUNBUFRDSEEgRW50ZXJwcmlzZSBpbnRlcmZhY2VcbmV4cG9ydCBpbnRlcmZhY2UgR3JlQ0FQVENIQSB7XG4gIHJlYWR5OiAoY2FsbGJhY2s6ICgpID0+IHZvaWQpID0+IHZvaWQ7XG4gIGV4ZWN1dGU6IChzaXRlS2V5OiBzdHJpbmcsIG9wdGlvbnM6IHsgYWN0aW9uOiBzdHJpbmcgfSkgPT4gUHJvbWlzZTxzdHJpbmc+O1xuICByZW5kZXI6IChcbiAgICBjb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIHBhcmFtZXRlcnM6IEdyZUNBUFRDSEFSZW5kZXJPcHRpb25cbiAgKSA9PiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3JlQ0FQVENIQVJlbmRlck9wdGlvbiB7XG4gIHNpdGVrZXk6IHN0cmluZztcbiAgc2l6ZTogJ2ludmlzaWJsZSc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0VudGVycHJpc2UoXG4gIGdyZWNhcHRjaGE6IFJlY2FwdGNoYSB8IEdyZUNBUFRDSEEgfCB1bmRlZmluZWRcbik6IGdyZWNhcHRjaGEgaXMgR3JlQ0FQVENIQVRvcExldmVsIHtcbiAgcmV0dXJuIChcbiAgICBncmVjYXB0Y2hhICE9PSB1bmRlZmluZWQgJiZcbiAgICAoZ3JlY2FwdGNoYSBhcyBHcmVDQVBUQ0hBVG9wTGV2ZWwpLmVudGVycHJpc2UgIT09IHVuZGVmaW5lZFxuICApO1xufVxuXG4vLyBUT0RPKGNodWFucik6IFJlcGxhY2UgdGhpcyB3aXRoIHRoZSBBdXRoV2luZG93IGFmdGVyIHJlc29sdmluZyB0aGUgZGVwZW5kZW5jeSBpc3N1ZSBpbiBOb2RlLmpzIGVudi5cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgaW50ZXJmYWNlIFdpbmRvdyB7XG4gICAgZ3JlY2FwdGNoYT86IFJlY2FwdGNoYSB8IEdyZUNBUFRDSEFUb3BMZXZlbDtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUmVjYXB0Y2hhQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSByZUNBUFRDSEEgc2l0ZSBrZXkuXG4gICAqL1xuICBzaXRlS2V5OiBzdHJpbmcgPSAnJztcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgcHJvdmlkZXJzIGFuZCB0aGVpciBlbmFibGVtZW50IHN0YXR1cyBmb3IgcmVDQVBUQ0hBIEVudGVycHJpc2UuXG4gICAqL1xuICByZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlOiBSZWNhcHRjaGFFbmZvcmNlbWVudFByb3ZpZGVyU3RhdGVbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKHJlc3BvbnNlOiBHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZSkge1xuICAgIGlmIChyZXNwb25zZS5yZWNhcHRjaGFLZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWNhcHRjaGFLZXkgdW5kZWZpbmVkJyk7XG4gICAgfVxuICAgIC8vIEV4YW1wbGUgcmVzcG9uc2UucmVjYXB0Y2hhS2V5OiBcInByb2plY3RzL3Byb2oxMjMva2V5cy9zaXRla2V5MTIzXCJcbiAgICB0aGlzLnNpdGVLZXkgPSByZXNwb25zZS5yZWNhcHRjaGFLZXkuc3BsaXQoJy8nKVszXTtcbiAgICB0aGlzLnJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUgPSByZXNwb25zZS5yZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHJlQ0FQVENIQSBFbnRlcnByaXNlIGVuZm9yY2VtZW50IHN0YXRlIGZvciB0aGUgZ2l2ZW4gcHJvdmlkZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwcm92aWRlclN0ciAtIFRoZSBwcm92aWRlciB3aG9zZSBlbmZvcmNlbWVudCBzdGF0ZSBpcyB0byBiZSByZXR1cm5lZC5cbiAgICogQHJldHVybnMgVGhlIHJlQ0FQVENIQSBFbnRlcnByaXNlIGVuZm9yY2VtZW50IHN0YXRlIGZvciB0aGUgZ2l2ZW4gcHJvdmlkZXIuXG4gICAqL1xuICBnZXRQcm92aWRlckVuZm9yY2VtZW50U3RhdGUocHJvdmlkZXJTdHI6IHN0cmluZyk6IEVuZm9yY2VtZW50U3RhdGUgfCBudWxsIHtcbiAgICBpZiAoXG4gICAgICAhdGhpcy5yZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlIHx8XG4gICAgICB0aGlzLnJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUubGVuZ3RoID09PSAwXG4gICAgKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUgb2YgdGhpcy5yZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHJlY2FwdGNoYUVuZm9yY2VtZW50U3RhdGUucHJvdmlkZXIgJiZcbiAgICAgICAgcmVjYXB0Y2hhRW5mb3JjZW1lbnRTdGF0ZS5wcm92aWRlciA9PT0gcHJvdmlkZXJTdHJcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gX3BhcnNlRW5mb3JjZW1lbnRTdGF0ZShcbiAgICAgICAgICByZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlLmVuZm9yY2VtZW50U3RhdGVcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoZSByZUNBUFRDSEEgRW50ZXJwcmlzZSBlbmZvcmNlbWVudCBzdGF0ZSBmb3IgdGhlIHByb3ZpZGVyIGlzIHNldCB0byBFTkZPUkNFIG9yIEFVRElULlxuICAgKlxuICAgKiBAcGFyYW0gcHJvdmlkZXJTdHIgLSBUaGUgcHJvdmlkZXIgd2hvc2UgZW5hYmxlbWVudCBzdGF0ZSBpcyB0byBiZSByZXR1cm5lZC5cbiAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgcmVDQVBUQ0hBIEVudGVycHJpc2UgcHJvdGVjdGlvbiBpcyBlbmFibGVkIGZvciB0aGUgZ2l2ZW4gcHJvdmlkZXIuXG4gICAqL1xuICBpc1Byb3ZpZGVyRW5hYmxlZChwcm92aWRlclN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuZ2V0UHJvdmlkZXJFbmZvcmNlbWVudFN0YXRlKHByb3ZpZGVyU3RyKSA9PT1cbiAgICAgICAgRW5mb3JjZW1lbnRTdGF0ZS5FTkZPUkNFIHx8XG4gICAgICB0aGlzLmdldFByb3ZpZGVyRW5mb3JjZW1lbnRTdGF0ZShwcm92aWRlclN0cikgPT09IEVuZm9yY2VtZW50U3RhdGUuQVVESVRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiByZUNBUFRDSEEgRW50ZXJwcmlzZSBwcm90ZWN0aW9uIGlzIGVuYWJsZWQgaW4gYXQgbGVhc3Qgb25lIHByb3ZpZGVyLCBvdGhlcndpc2VcbiAgICogcmV0dXJucyBmYWxzZS5cbiAgICpcbiAgICogQHJldHVybnMgV2hldGhlciBvciBub3QgcmVDQVBUQ0hBIEVudGVycHJpc2UgcHJvdGVjdGlvbiBpcyBlbmFibGVkIGZvciBhdCBsZWFzdCBvbmUgcHJvdmlkZXIuXG4gICAqL1xuICBpc0FueVByb3ZpZGVyRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5pc1Byb3ZpZGVyRW5hYmxlZChSZWNhcHRjaGFBdXRoUHJvdmlkZXIuRU1BSUxfUEFTU1dPUkRfUFJPVklERVIpIHx8XG4gICAgICB0aGlzLmlzUHJvdmlkZXJFbmFibGVkKFJlY2FwdGNoYUF1dGhQcm92aWRlci5QSE9ORV9QUk9WSURFUilcbiAgICApO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYVZlcnNpb24sXG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgX2FkZFRpZElmTmVjZXNzYXJ5XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEF1dGggfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbnRlcmZhY2UgR2V0UmVjYXB0Y2hhUGFyYW1SZXNwb25zZSB7XG4gIHJlY2FwdGNoYVNpdGVLZXk/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSZWNhcHRjaGFQYXJhbXMoYXV0aDogQXV0aCk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiAoXG4gICAgKFxuICAgICAgYXdhaXQgX3BlcmZvcm1BcGlSZXF1ZXN0PHZvaWQsIEdldFJlY2FwdGNoYVBhcmFtUmVzcG9uc2U+KFxuICAgICAgICBhdXRoLFxuICAgICAgICBIdHRwTWV0aG9kLkdFVCxcbiAgICAgICAgRW5kcG9pbnQuR0VUX1JFQ0FQVENIQV9QQVJBTVxuICAgICAgKVxuICAgICkucmVjYXB0Y2hhU2l0ZUtleSB8fCAnJ1xuICApO1xufVxuXG4vLyBUaGUgZm9sbG93aW5nIGZ1bmN0aW9ucyBhcmUgZm9yIHJlQ0FQVENIQSBlbnRlcnByaXNlIGludGVncmF0aW9uLlxuaW50ZXJmYWNlIEdldFJlY2FwdGNoYUNvbmZpZ1JlcXVlc3Qge1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY2FwdGNoYUVuZm9yY2VtZW50UHJvdmlkZXJTdGF0ZSB7XG4gIHByb3ZpZGVyOiBzdHJpbmc7XG4gIGVuZm9yY2VtZW50U3RhdGU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZSB7XG4gIHJlY2FwdGNoYUtleTogc3RyaW5nO1xuICByZWNhcHRjaGFFbmZvcmNlbWVudFN0YXRlOiBSZWNhcHRjaGFFbmZvcmNlbWVudFByb3ZpZGVyU3RhdGVbXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFJlY2FwdGNoYUNvbmZpZyhcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogR2V0UmVjYXB0Y2hhQ29uZmlnUmVxdWVzdFxuKTogUHJvbWlzZTxHZXRSZWNhcHRjaGFDb25maWdSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIEdldFJlY2FwdGNoYUNvbmZpZ1JlcXVlc3QsXG4gICAgR2V0UmVjYXB0Y2hhQ29uZmlnUmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuR0VULFxuICAgIEVuZHBvaW50LkdFVF9SRUNBUFRDSEFfQ09ORklHLFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEVuZHBvaW50LCBIdHRwTWV0aG9kLCBfcGVyZm9ybUFwaVJlcXVlc3QgfSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBNZmFFbnJvbGxtZW50IH0gZnJvbSAnLi9tZmEnO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlQWNjb3VudFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVBY2NvdW50KFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBEZWxldGVBY2NvdW50UmVxdWVzdFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8RGVsZXRlQWNjb3VudFJlcXVlc3QsIHZvaWQ+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LkRFTEVURV9BQ0NPVU5ULFxuICAgIHJlcXVlc3RcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlclVzZXJJbmZvIHtcbiAgcHJvdmlkZXJJZDogc3RyaW5nO1xuICByYXdJZD86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xuICBwaG90b1VybD86IHN0cmluZztcbiAgcGhvbmVOdW1iZXI/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlTGlua2VkQWNjb3VudHNSZXF1ZXN0IHtcbiAgaWRUb2tlbjogc3RyaW5nO1xuICBkZWxldGVQcm92aWRlcjogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlTGlua2VkQWNjb3VudHNSZXNwb25zZSB7XG4gIHByb3ZpZGVyVXNlckluZm86IFByb3ZpZGVyVXNlckluZm9bXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZUxpbmtlZEFjY291bnRzKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBEZWxldGVMaW5rZWRBY2NvdW50c1JlcXVlc3Rcbik6IFByb21pc2U8RGVsZXRlTGlua2VkQWNjb3VudHNSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIERlbGV0ZUxpbmtlZEFjY291bnRzUmVxdWVzdCxcbiAgICBEZWxldGVMaW5rZWRBY2NvdW50c1Jlc3BvbnNlXG4gID4oYXV0aCwgSHR0cE1ldGhvZC5QT1NULCBFbmRwb2ludC5TRVRfQUNDT1VOVF9JTkZPLCByZXF1ZXN0KTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBUElVc2VySW5mbyB7XG4gIGxvY2FsSWQ/OiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xuICBwaG90b1VybD86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG4gIGVtYWlsVmVyaWZpZWQ/OiBib29sZWFuO1xuICBwaG9uZU51bWJlcj86IHN0cmluZztcbiAgbGFzdExvZ2luQXQ/OiBudW1iZXI7XG4gIGNyZWF0ZWRBdD86IG51bWJlcjtcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG4gIHBhc3N3b3JkSGFzaD86IHN0cmluZztcbiAgcHJvdmlkZXJVc2VySW5mbz86IFByb3ZpZGVyVXNlckluZm9bXTtcbiAgbWZhSW5mbz86IE1mYUVucm9sbG1lbnRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRBY2NvdW50SW5mb1JlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0QWNjb3VudEluZm9SZXNwb25zZSB7XG4gIHVzZXJzOiBBUElVc2VySW5mb1tdO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWNjb3VudEluZm8oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IEdldEFjY291bnRJbmZvUmVxdWVzdFxuKTogUHJvbWlzZTxHZXRBY2NvdW50SW5mb1Jlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8R2V0QWNjb3VudEluZm9SZXF1ZXN0LCBHZXRBY2NvdW50SW5mb1Jlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5HRVRfQUNDT1VOVF9JTkZPLFxuICAgIHJlcXVlc3RcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdXRjVGltZXN0YW1wVG9EYXRlU3RyaW5nKFxuICB1dGNUaW1lc3RhbXA/OiBzdHJpbmcgfCBudW1iZXJcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICghdXRjVGltZXN0YW1wKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICB0cnkge1xuICAgIC8vIENvbnZlcnQgdG8gZGF0ZSBvYmplY3QuXG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKE51bWJlcih1dGNUaW1lc3RhbXApKTtcbiAgICAvLyBUZXN0IGRhdGUgaXMgdmFsaWQuXG4gICAgaWYgKCFpc05hTihkYXRlLmdldFRpbWUoKSkpIHtcbiAgICAgIC8vIENvbnZlcnQgdG8gVVRDIGRhdGUgc3RyaW5nLlxuICAgICAgcmV0dXJuIGRhdGUudG9VVENTdHJpbmcoKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBEbyBub3RoaW5nLiB1bmRlZmluZWQgd2lsbCBiZSByZXR1cm5lZC5cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IElkVG9rZW5SZXN1bHQsIFBhcnNlZFRva2VuLCBVc2VyIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IGJhc2U2NERlY29kZSwgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfbG9nRXJyb3IgfSBmcm9tICcuLi91dGlsL2xvZyc7XG5pbXBvcnQgeyB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcgfSBmcm9tICcuLi91dGlsL3RpbWUnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbi8qKlxuICogUmV0dXJucyBhIEpTT04gV2ViIFRva2VuIChKV1QpIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHVzZXIgdG8gYSBGaXJlYmFzZSBzZXJ2aWNlLlxuICpcbiAqIEByZW1hcmtzXG4gKiBSZXR1cm5zIHRoZSBjdXJyZW50IHRva2VuIGlmIGl0IGhhcyBub3QgZXhwaXJlZCBvciBpZiBpdCB3aWxsIG5vdCBleHBpcmUgaW4gdGhlIG5leHQgZml2ZVxuICogbWludXRlcy4gT3RoZXJ3aXNlLCB0aGlzIHdpbGwgcmVmcmVzaCB0aGUgdG9rZW4gYW5kIHJldHVybiBhIG5ldyBvbmUuXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBmb3JjZVJlZnJlc2ggLSBGb3JjZSByZWZyZXNoIHJlZ2FyZGxlc3Mgb2YgdG9rZW4gZXhwaXJhdGlvbi5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJZFRva2VuKHVzZXI6IFVzZXIsIGZvcmNlUmVmcmVzaCA9IGZhbHNlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKS5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGRlc2VyaWFsaXplZCBKU09OIFdlYiBUb2tlbiAoSldUKSB1c2VkIHRvIGlkZW50aWZ5IHRoZSB1c2VyIHRvIGEgRmlyZWJhc2Ugc2VydmljZS5cbiAqXG4gKiBAcmVtYXJrc1xuICogUmV0dXJucyB0aGUgY3VycmVudCB0b2tlbiBpZiBpdCBoYXMgbm90IGV4cGlyZWQgb3IgaWYgaXQgd2lsbCBub3QgZXhwaXJlIGluIHRoZSBuZXh0IGZpdmVcbiAqIG1pbnV0ZXMuIE90aGVyd2lzZSwgdGhpcyB3aWxsIHJlZnJlc2ggdGhlIHRva2VuIGFuZCByZXR1cm4gYSBuZXcgb25lLlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gZm9yY2VSZWZyZXNoIC0gRm9yY2UgcmVmcmVzaCByZWdhcmRsZXNzIG9mIHRva2VuIGV4cGlyYXRpb24uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0SWRUb2tlblJlc3VsdChcbiAgdXNlcjogVXNlcixcbiAgZm9yY2VSZWZyZXNoID0gZmFsc2Vcbik6IFByb21pc2U8SWRUb2tlblJlc3VsdD4ge1xuICBjb25zdCB1c2VySW50ZXJuYWwgPSBnZXRNb2R1bGFySW5zdGFuY2UodXNlcikgYXMgVXNlckludGVybmFsO1xuICBjb25zdCB0b2tlbiA9IGF3YWl0IHVzZXJJbnRlcm5hbC5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG4gIGNvbnN0IGNsYWltcyA9IF9wYXJzZVRva2VuKHRva2VuKTtcblxuICBfYXNzZXJ0KFxuICAgIGNsYWltcyAmJiBjbGFpbXMuZXhwICYmIGNsYWltcy5hdXRoX3RpbWUgJiYgY2xhaW1zLmlhdCxcbiAgICB1c2VySW50ZXJuYWwuYXV0aCxcbiAgICBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SXG4gICk7XG4gIGNvbnN0IGZpcmViYXNlID1cbiAgICB0eXBlb2YgY2xhaW1zLmZpcmViYXNlID09PSAnb2JqZWN0JyA/IGNsYWltcy5maXJlYmFzZSA6IHVuZGVmaW5lZDtcblxuICBjb25zdCBzaWduSW5Qcm92aWRlcjogc3RyaW5nIHwgdW5kZWZpbmVkID0gZmlyZWJhc2U/Llsnc2lnbl9pbl9wcm92aWRlciddO1xuXG4gIHJldHVybiB7XG4gICAgY2xhaW1zLFxuICAgIHRva2VuLFxuICAgIGF1dGhUaW1lOiB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcoXG4gICAgICBzZWNvbmRzU3RyaW5nVG9NaWxsaXNlY29uZHMoY2xhaW1zLmF1dGhfdGltZSlcbiAgICApISxcbiAgICBpc3N1ZWRBdFRpbWU6IHV0Y1RpbWVzdGFtcFRvRGF0ZVN0cmluZyhcbiAgICAgIHNlY29uZHNTdHJpbmdUb01pbGxpc2Vjb25kcyhjbGFpbXMuaWF0KVxuICAgICkhLFxuICAgIGV4cGlyYXRpb25UaW1lOiB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcoXG4gICAgICBzZWNvbmRzU3RyaW5nVG9NaWxsaXNlY29uZHMoY2xhaW1zLmV4cClcbiAgICApISxcbiAgICBzaWduSW5Qcm92aWRlcjogc2lnbkluUHJvdmlkZXIgfHwgbnVsbCxcbiAgICBzaWduSW5TZWNvbmRGYWN0b3I6IGZpcmViYXNlPy5bJ3NpZ25faW5fc2Vjb25kX2ZhY3RvciddIHx8IG51bGxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2Vjb25kc1N0cmluZ1RvTWlsbGlzZWNvbmRzKHNlY29uZHM6IHN0cmluZyk6IG51bWJlciB7XG4gIHJldHVybiBOdW1iZXIoc2Vjb25kcykgKiAxMDAwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3BhcnNlVG9rZW4odG9rZW46IHN0cmluZyk6IFBhcnNlZFRva2VuIHwgbnVsbCB7XG4gIGNvbnN0IFthbGdvcml0aG0sIHBheWxvYWQsIHNpZ25hdHVyZV0gPSB0b2tlbi5zcGxpdCgnLicpO1xuICBpZiAoXG4gICAgYWxnb3JpdGhtID09PSB1bmRlZmluZWQgfHxcbiAgICBwYXlsb2FkID09PSB1bmRlZmluZWQgfHxcbiAgICBzaWduYXR1cmUgPT09IHVuZGVmaW5lZFxuICApIHtcbiAgICBfbG9nRXJyb3IoJ0pXVCBtYWxmb3JtZWQsIGNvbnRhaW5lZCBmZXdlciB0aGFuIDMgc2VjdGlvbnMnKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHRyeSB7XG4gICAgY29uc3QgZGVjb2RlZCA9IGJhc2U2NERlY29kZShwYXlsb2FkKTtcbiAgICBpZiAoIWRlY29kZWQpIHtcbiAgICAgIF9sb2dFcnJvcignRmFpbGVkIHRvIGRlY29kZSBiYXNlNjQgSldUIHBheWxvYWQnKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gSlNPTi5wYXJzZShkZWNvZGVkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIF9sb2dFcnJvcihcbiAgICAgICdDYXVnaHQgZXJyb3IgcGFyc2luZyBKV1QgcGF5bG9hZCBhcyBKU09OJyxcbiAgICAgIChlIGFzIEVycm9yKT8udG9TdHJpbmcoKVxuICAgICk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBFeHRyYWN0IGV4cGlyZXNJbiBUVEwgZnJvbSBhIHRva2VuIGJ5IHN1YnRyYWN0aW5nIHRoZSBleHBpcmF0aW9uIGZyb20gdGhlIGlzc3VhbmNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gX3Rva2VuRXhwaXJlc0luKHRva2VuOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCBwYXJzZWRUb2tlbiA9IF9wYXJzZVRva2VuKHRva2VuKTtcbiAgX2Fzc2VydChwYXJzZWRUb2tlbiwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gIF9hc3NlcnQodHlwZW9mIHBhcnNlZFRva2VuLmV4cCAhPT0gJ3VuZGVmaW5lZCcsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICBfYXNzZXJ0KHR5cGVvZiBwYXJzZWRUb2tlbi5pYXQgIT09ICd1bmRlZmluZWQnLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgcmV0dXJuIE51bWJlcihwYXJzZWRUb2tlbi5leHApIC0gTnVtYmVyKHBhcnNlZFRva2VuLmlhdCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9sb2dvdXRJZkludmFsaWRhdGVkPFQ+KFxuICB1c2VyOiBVc2VySW50ZXJuYWwsXG4gIHByb21pc2U6IFByb21pc2U8VD4sXG4gIGJ5cGFzc0F1dGhTdGF0ZSA9IGZhbHNlXG4pOiBQcm9taXNlPFQ+IHtcbiAgaWYgKGJ5cGFzc0F1dGhTdGF0ZSkge1xuICAgIHJldHVybiBwcm9taXNlO1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHByb21pc2U7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIEZpcmViYXNlRXJyb3IgJiYgaXNVc2VySW52YWxpZGF0ZWQoZSkpIHtcbiAgICAgIGlmICh1c2VyLmF1dGguY3VycmVudFVzZXIgPT09IHVzZXIpIHtcbiAgICAgICAgYXdhaXQgdXNlci5hdXRoLnNpZ25PdXQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzVXNlckludmFsaWRhdGVkKHsgY29kZSB9OiBGaXJlYmFzZUVycm9yKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgY29kZSA9PT0gYGF1dGgvJHtBdXRoRXJyb3JDb2RlLlVTRVJfRElTQUJMRUR9YCB8fFxuICAgIGNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5UT0tFTl9FWFBJUkVEfWBcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuLy8gUmVmcmVzaCB0aGUgdG9rZW4gZml2ZSBtaW51dGVzIGJlZm9yZSBleHBpcmF0aW9uXG5leHBvcnQgY29uc3QgZW51bSBEdXJhdGlvbiB7XG4gIE9GRlNFVCA9IDUgKiAxMDAwICogNjAsXG4gIFJFVFJZX0JBQ0tPRkZfTUlOID0gMzAgKiAxMDAwLFxuICBSRVRSWV9CQUNLT0ZGX01BWCA9IDE2ICogNjAgKiAxMDAwXG59XG5cbmV4cG9ydCBjbGFzcyBQcm9hY3RpdmVSZWZyZXNoIHtcbiAgcHJpdmF0ZSBpc1J1bm5pbmcgPSBmYWxzZTtcblxuICAvLyBOb2RlIHRpbWVycyBhbmQgYnJvd3NlciB0aW1lcnMgcmV0dXJuIGZ1bmRhbWVudGFsbHkgZGlmZmVyZW50IHR5cGVzLlxuICAvLyBXZSBkb24ndCBhY3R1YWxseSBjYXJlIHdoYXQgdGhlIHZhbHVlIGlzIGJ1dCBUUyB3b24ndCBhY2NlcHQgdW5rbm93biBhbmRcbiAgLy8gd2UgY2FuJ3QgY2FzdCBwcm9wZXJseSBpbiBib3RoIGVudmlyb25tZW50cy5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgcHJpdmF0ZSB0aW1lcklkOiBhbnkgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBlcnJvckJhY2tvZmYgPSBEdXJhdGlvbi5SRVRSWV9CQUNLT0ZGX01JTjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHVzZXI6IFVzZXJJbnRlcm5hbCkge31cblxuICBfc3RhcnQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNSdW5uaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5pc1J1bm5pbmcgPSB0cnVlO1xuICAgIHRoaXMuc2NoZWR1bGUoKTtcbiAgfVxuXG4gIF9zdG9wKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc1J1bm5pbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlzUnVubmluZyA9IGZhbHNlO1xuICAgIGlmICh0aGlzLnRpbWVySWQgIT09IG51bGwpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVySWQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0SW50ZXJ2YWwod2FzRXJyb3I6IGJvb2xlYW4pOiBudW1iZXIge1xuICAgIGlmICh3YXNFcnJvcikge1xuICAgICAgY29uc3QgaW50ZXJ2YWwgPSB0aGlzLmVycm9yQmFja29mZjtcbiAgICAgIHRoaXMuZXJyb3JCYWNrb2ZmID0gTWF0aC5taW4oXG4gICAgICAgIHRoaXMuZXJyb3JCYWNrb2ZmICogMixcbiAgICAgICAgRHVyYXRpb24uUkVUUllfQkFDS09GRl9NQVhcbiAgICAgICk7XG4gICAgICByZXR1cm4gaW50ZXJ2YWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlc2V0IHRoZSBlcnJvciBiYWNrb2ZmXG4gICAgICB0aGlzLmVycm9yQmFja29mZiA9IER1cmF0aW9uLlJFVFJZX0JBQ0tPRkZfTUlOO1xuICAgICAgY29uc3QgZXhwVGltZSA9IHRoaXMudXNlci5zdHNUb2tlbk1hbmFnZXIuZXhwaXJhdGlvblRpbWUgPz8gMDtcbiAgICAgIGNvbnN0IGludGVydmFsID0gZXhwVGltZSAtIERhdGUubm93KCkgLSBEdXJhdGlvbi5PRkZTRVQ7XG5cbiAgICAgIHJldHVybiBNYXRoLm1heCgwLCBpbnRlcnZhbCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzY2hlZHVsZSh3YXNFcnJvciA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzUnVubmluZykge1xuICAgICAgLy8gSnVzdCBpbiBjYXNlLi4uXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaW50ZXJ2YWwgPSB0aGlzLmdldEludGVydmFsKHdhc0Vycm9yKTtcbiAgICB0aGlzLnRpbWVySWQgPSBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMuaXRlcmF0aW9uKCk7XG4gICAgfSwgaW50ZXJ2YWwpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpdGVyYXRpb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudXNlci5nZXRJZFRva2VuKHRydWUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIE9ubHkgcmV0cnkgb24gbmV0d29yayBlcnJvcnNcbiAgICAgIGlmIChcbiAgICAgICAgKGUgYXMgRmlyZWJhc2VFcnJvcik/LmNvZGUgPT09XG4gICAgICAgIGBhdXRoLyR7QXV0aEVycm9yQ29kZS5ORVRXT1JLX1JFUVVFU1RfRkFJTEVEfWBcbiAgICAgICkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlKC8qIHdhc0Vycm9yICovIHRydWUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc2NoZWR1bGUoKTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXJNZXRhZGF0YSBhcyBVc2VyTWV0YWRhdGFUeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgdXRjVGltZXN0YW1wVG9EYXRlU3RyaW5nIH0gZnJvbSAnLi4vdXRpbC90aW1lJztcblxuZXhwb3J0IGNsYXNzIFVzZXJNZXRhZGF0YSBpbXBsZW1lbnRzIFVzZXJNZXRhZGF0YVR5cGUge1xuICBjcmVhdGlvblRpbWU/OiBzdHJpbmc7XG4gIGxhc3RTaWduSW5UaW1lPzogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY3JlYXRlZEF0Pzogc3RyaW5nIHwgbnVtYmVyLFxuICAgIHByaXZhdGUgbGFzdExvZ2luQXQ/OiBzdHJpbmcgfCBudW1iZXJcbiAgKSB7XG4gICAgdGhpcy5faW5pdGlhbGl6ZVRpbWUoKTtcbiAgfVxuXG4gIHByaXZhdGUgX2luaXRpYWxpemVUaW1lKCk6IHZvaWQge1xuICAgIHRoaXMubGFzdFNpZ25JblRpbWUgPSB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcodGhpcy5sYXN0TG9naW5BdCk7XG4gICAgdGhpcy5jcmVhdGlvblRpbWUgPSB1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmcodGhpcy5jcmVhdGVkQXQpO1xuICB9XG5cbiAgX2NvcHkobWV0YWRhdGE6IFVzZXJNZXRhZGF0YSk6IHZvaWQge1xuICAgIHRoaXMuY3JlYXRlZEF0ID0gbWV0YWRhdGEuY3JlYXRlZEF0O1xuICAgIHRoaXMubGFzdExvZ2luQXQgPSBtZXRhZGF0YS5sYXN0TG9naW5BdDtcbiAgICB0aGlzLl9pbml0aWFsaXplVGltZSgpO1xuICB9XG5cbiAgdG9KU09OKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNyZWF0ZWRBdDogdGhpcy5jcmVhdGVkQXQsXG4gICAgICBsYXN0TG9naW5BdDogdGhpcy5sYXN0TG9naW5BdFxuICAgIH07XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVc2VyLCBVc2VySW5mbyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7XG4gIGdldEFjY291bnRJbmZvLFxuICBQcm92aWRlclVzZXJJbmZvXG59IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvYWNjb3VudCc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCB9IGZyb20gJy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgVXNlck1ldGFkYXRhIH0gZnJvbSAnLi91c2VyX21ldGFkYXRhJztcbmltcG9ydCB7IGdldE1vZHVsYXJJbnN0YW5jZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9yZWxvYWRXaXRob3V0U2F2aW5nKHVzZXI6IFVzZXJJbnRlcm5hbCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhdXRoID0gdXNlci5hdXRoO1xuICBjb25zdCBpZFRva2VuID0gYXdhaXQgdXNlci5nZXRJZFRva2VuKCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQoXG4gICAgdXNlcixcbiAgICBnZXRBY2NvdW50SW5mbyhhdXRoLCB7IGlkVG9rZW4gfSlcbiAgKTtcblxuICBfYXNzZXJ0KHJlc3BvbnNlPy51c2Vycy5sZW5ndGgsIGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuXG4gIGNvbnN0IGNvcmVBY2NvdW50ID0gcmVzcG9uc2UudXNlcnNbMF07XG5cbiAgdXNlci5fbm90aWZ5UmVsb2FkTGlzdGVuZXIoY29yZUFjY291bnQpO1xuXG4gIGNvbnN0IG5ld1Byb3ZpZGVyRGF0YSA9IGNvcmVBY2NvdW50LnByb3ZpZGVyVXNlckluZm8/Lmxlbmd0aFxuICAgID8gZXh0cmFjdFByb3ZpZGVyRGF0YShjb3JlQWNjb3VudC5wcm92aWRlclVzZXJJbmZvKVxuICAgIDogW107XG5cbiAgY29uc3QgcHJvdmlkZXJEYXRhID0gbWVyZ2VQcm92aWRlckRhdGEodXNlci5wcm92aWRlckRhdGEsIG5ld1Byb3ZpZGVyRGF0YSk7XG5cbiAgLy8gUHJlc2VydmVzIHRoZSBub24tbm9ueW1vdXMgc3RhdHVzIG9mIHRoZSBzdG9yZWQgdXNlciwgZXZlbiBpZiBubyBtb3JlXG4gIC8vIGNyZWRlbnRpYWxzIChmZWRlcmF0ZWQgb3IgZW1haWwvcGFzc3dvcmQpIGFyZSBsaW5rZWQgdG8gdGhlIHVzZXIuIElmXG4gIC8vIHRoZSB1c2VyIHdhcyBwcmV2aW91c2x5IGFub255bW91cywgdGhlbiB1c2UgcHJvdmlkZXIgZGF0YSB0byB1cGRhdGUuXG4gIC8vIE9uIHRoZSBvdGhlciBoYW5kLCBpZiBpdCB3YXMgbm90IGFub255bW91cyBiZWZvcmUsIGl0IHNob3VsZCBuZXZlciBiZVxuICAvLyBjb25zaWRlcmVkIGFub255bW91cyBub3cuXG4gIGNvbnN0IG9sZElzQW5vbnltb3VzID0gdXNlci5pc0Fub255bW91cztcbiAgY29uc3QgbmV3SXNBbm9ueW1vdXMgPVxuICAgICEodXNlci5lbWFpbCAmJiBjb3JlQWNjb3VudC5wYXNzd29yZEhhc2gpICYmICFwcm92aWRlckRhdGE/Lmxlbmd0aDtcbiAgY29uc3QgaXNBbm9ueW1vdXMgPSAhb2xkSXNBbm9ueW1vdXMgPyBmYWxzZSA6IG5ld0lzQW5vbnltb3VzO1xuXG4gIGNvbnN0IHVwZGF0ZXM6IFBhcnRpYWw8VXNlckludGVybmFsPiA9IHtcbiAgICB1aWQ6IGNvcmVBY2NvdW50LmxvY2FsSWQsXG4gICAgZGlzcGxheU5hbWU6IGNvcmVBY2NvdW50LmRpc3BsYXlOYW1lIHx8IG51bGwsXG4gICAgcGhvdG9VUkw6IGNvcmVBY2NvdW50LnBob3RvVXJsIHx8IG51bGwsXG4gICAgZW1haWw6IGNvcmVBY2NvdW50LmVtYWlsIHx8IG51bGwsXG4gICAgZW1haWxWZXJpZmllZDogY29yZUFjY291bnQuZW1haWxWZXJpZmllZCB8fCBmYWxzZSxcbiAgICBwaG9uZU51bWJlcjogY29yZUFjY291bnQucGhvbmVOdW1iZXIgfHwgbnVsbCxcbiAgICB0ZW5hbnRJZDogY29yZUFjY291bnQudGVuYW50SWQgfHwgbnVsbCxcbiAgICBwcm92aWRlckRhdGEsXG4gICAgbWV0YWRhdGE6IG5ldyBVc2VyTWV0YWRhdGEoY29yZUFjY291bnQuY3JlYXRlZEF0LCBjb3JlQWNjb3VudC5sYXN0TG9naW5BdCksXG4gICAgaXNBbm9ueW1vdXNcbiAgfTtcblxuICBPYmplY3QuYXNzaWduKHVzZXIsIHVwZGF0ZXMpO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdXNlciBhY2NvdW50IGRhdGEsIGlmIHNpZ25lZCBpbi5cbiAqXG4gKiBAcGFyYW0gdXNlciAtIFRoZSB1c2VyLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbG9hZCh1c2VyOiBVc2VyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbDogVXNlckludGVybmFsID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbDtcbiAgYXdhaXQgX3JlbG9hZFdpdGhvdXRTYXZpbmcodXNlckludGVybmFsKTtcblxuICAvLyBFdmVuIHRob3VnaCB0aGUgY3VycmVudCB1c2VyIGhhc24ndCBjaGFuZ2VkLCB1cGRhdGVcbiAgLy8gY3VycmVudCB1c2VyIHdpbGwgdHJpZ2dlciBhIHBlcnNpc3RlbmNlIHVwZGF0ZSB3LyB0aGVcbiAgLy8gbmV3IGluZm8uXG4gIGF3YWl0IHVzZXJJbnRlcm5hbC5hdXRoLl9wZXJzaXN0VXNlcklmQ3VycmVudCh1c2VySW50ZXJuYWwpO1xuICB1c2VySW50ZXJuYWwuYXV0aC5fbm90aWZ5TGlzdGVuZXJzSWZDdXJyZW50KHVzZXJJbnRlcm5hbCk7XG59XG5cbmZ1bmN0aW9uIG1lcmdlUHJvdmlkZXJEYXRhKFxuICBvcmlnaW5hbDogVXNlckluZm9bXSxcbiAgbmV3RGF0YTogVXNlckluZm9bXVxuKTogVXNlckluZm9bXSB7XG4gIGNvbnN0IGRlZHVwZWQgPSBvcmlnaW5hbC5maWx0ZXIoXG4gICAgbyA9PiAhbmV3RGF0YS5zb21lKG4gPT4gbi5wcm92aWRlcklkID09PSBvLnByb3ZpZGVySWQpXG4gICk7XG4gIHJldHVybiBbLi4uZGVkdXBlZCwgLi4ubmV3RGF0YV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0UHJvdmlkZXJEYXRhKHByb3ZpZGVyczogUHJvdmlkZXJVc2VySW5mb1tdKTogVXNlckluZm9bXSB7XG4gIHJldHVybiBwcm92aWRlcnMubWFwKCh7IHByb3ZpZGVySWQsIC4uLnByb3ZpZGVyIH0pID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgcHJvdmlkZXJJZCxcbiAgICAgIHVpZDogcHJvdmlkZXIucmF3SWQgfHwgJycsXG4gICAgICBkaXNwbGF5TmFtZTogcHJvdmlkZXIuZGlzcGxheU5hbWUgfHwgbnVsbCxcbiAgICAgIGVtYWlsOiBwcm92aWRlci5lbWFpbCB8fCBudWxsLFxuICAgICAgcGhvbmVOdW1iZXI6IHByb3ZpZGVyLnBob25lTnVtYmVyIHx8IG51bGwsXG4gICAgICBwaG90b1VSTDogcHJvdmlkZXIucGhvdG9VcmwgfHwgbnVsbFxuICAgIH07XG4gIH0pO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qIGVzbGludC1kaXNhYmxlIGNhbWVsY2FzZSAqL1xuXG5pbXBvcnQgeyBpc0Nsb3VkV29ya3N0YXRpb24sIHF1ZXJ5c3RyaW5nIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQge1xuICBfZ2V0RmluYWxUYXJnZXQsXG4gIF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZyxcbiAgX3BlcmZvcm1BcGlSZXF1ZXN0LFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIEh0dHBNZXRob2QsXG4gIEh0dHBIZWFkZXIsXG4gIEVuZHBvaW50XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEZldGNoUHJvdmlkZXIgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvZmV0Y2hfcHJvdmlkZXInO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcblxuZXhwb3J0IGNvbnN0IGVudW0gVG9rZW5UeXBlIHtcbiAgUkVGUkVTSF9UT0tFTiA9ICdSRUZSRVNIX1RPS0VOJyxcbiAgQUNDRVNTX1RPS0VOID0gJ0FDQ0VTU19UT0tFTidcbn1cblxuLyoqIFRoZSBzZXJ2ZXIgcmVzcG9uc2VzIHdpdGggc25ha2VfY2FzZTsgd2UgY29udmVydCB0byBjYW1lbENhc2UgKi9cbmludGVyZmFjZSBSZXF1ZXN0U3RzVG9rZW5TZXJ2ZXJSZXNwb25zZSB7XG4gIGFjY2Vzc190b2tlbjogc3RyaW5nO1xuICBleHBpcmVzX2luOiBzdHJpbmc7XG4gIHJlZnJlc2hfdG9rZW46IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0U3RzVG9rZW5SZXNwb25zZSB7XG4gIGFjY2Vzc1Rva2VuOiBzdHJpbmc7XG4gIGV4cGlyZXNJbjogc3RyaW5nO1xuICByZWZyZXNoVG9rZW46IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXZva2VUb2tlblJlcXVlc3Qge1xuICBwcm92aWRlcklkOiBzdHJpbmc7XG4gIHRva2VuVHlwZTogVG9rZW5UeXBlO1xuICB0b2tlbjogc3RyaW5nO1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJldm9rZVRva2VuUmVzcG9uc2Uge31cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlcXVlc3RTdHNUb2tlbihcbiAgYXV0aDogQXV0aCxcbiAgcmVmcmVzaFRva2VuOiBzdHJpbmdcbik6IFByb21pc2U8UmVxdWVzdFN0c1Rva2VuUmVzcG9uc2U+IHtcbiAgY29uc3QgcmVzcG9uc2UgPVxuICAgIGF3YWl0IF9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZzxSZXF1ZXN0U3RzVG9rZW5TZXJ2ZXJSZXNwb25zZT4oXG4gICAgICBhdXRoLFxuICAgICAge30sXG4gICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBxdWVyeXN0cmluZyh7XG4gICAgICAgICAgJ2dyYW50X3R5cGUnOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgICAgJ3JlZnJlc2hfdG9rZW4nOiByZWZyZXNoVG9rZW5cbiAgICAgICAgfSkuc2xpY2UoMSk7XG4gICAgICAgIGNvbnN0IHsgdG9rZW5BcGlIb3N0LCBhcGlLZXkgfSA9IGF1dGguY29uZmlnO1xuICAgICAgICBjb25zdCB1cmwgPSBhd2FpdCBfZ2V0RmluYWxUYXJnZXQoXG4gICAgICAgICAgYXV0aCxcbiAgICAgICAgICB0b2tlbkFwaUhvc3QsXG4gICAgICAgICAgRW5kcG9pbnQuVE9LRU4sXG4gICAgICAgICAgYGtleT0ke2FwaUtleX1gXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgaGVhZGVycyA9IGF3YWl0IChhdXRoIGFzIEF1dGhJbnRlcm5hbCkuX2dldEFkZGl0aW9uYWxIZWFkZXJzKCk7XG4gICAgICAgIGhlYWRlcnNbSHR0cEhlYWRlci5DT05URU5UX1RZUEVdID0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCc7XG5cbiAgICAgICAgY29uc3Qgb3B0aW9uczogUmVxdWVzdEluaXQgPSB7XG4gICAgICAgICAgbWV0aG9kOiBIdHRwTWV0aG9kLlBPU1QsXG4gICAgICAgICAgaGVhZGVycyxcbiAgICAgICAgICBib2R5XG4gICAgICAgIH07XG4gICAgICAgIGlmIChcbiAgICAgICAgICBhdXRoLmVtdWxhdG9yQ29uZmlnICYmXG4gICAgICAgICAgaXNDbG91ZFdvcmtzdGF0aW9uKGF1dGguZW11bGF0b3JDb25maWcuaG9zdClcbiAgICAgICAgKSB7XG4gICAgICAgICAgb3B0aW9ucy5jcmVkZW50aWFscyA9ICdpbmNsdWRlJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRmV0Y2hQcm92aWRlci5mZXRjaCgpKHVybCwgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgKTtcblxuICAvLyBUaGUgcmVzcG9uc2UgY29tZXMgYmFjayBpbiBzbmFrZV9jYXNlLiBDb252ZXJ0IHRvIGNhbWVsOlxuICByZXR1cm4ge1xuICAgIGFjY2Vzc1Rva2VuOiByZXNwb25zZS5hY2Nlc3NfdG9rZW4sXG4gICAgZXhwaXJlc0luOiByZXNwb25zZS5leHBpcmVzX2luLFxuICAgIHJlZnJlc2hUb2tlbjogcmVzcG9uc2UucmVmcmVzaF90b2tlblxuICB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmV2b2tlVG9rZW4oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFJldm9rZVRva2VuUmVxdWVzdFxuKTogUHJvbWlzZTxSZXZva2VUb2tlblJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8UmV2b2tlVG9rZW5SZXF1ZXN0LCBSZXZva2VUb2tlblJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5SRVZPS0VfVE9LRU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgRmluYWxpemVNZmFSZXNwb25zZSB9IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9tZmEnO1xuaW1wb3J0IHsgcmVxdWVzdFN0c1Rva2VuIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL3Rva2VuJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBQZXJzaXN0ZWRCbG9iIH0gZnJvbSAnLi4vcGVyc2lzdGVuY2UnO1xuaW1wb3J0IHsgX2Fzc2VydCwgZGVidWdGYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgX3Rva2VuRXhwaXJlc0luIH0gZnJvbSAnLi9pZF90b2tlbl9yZXN1bHQnO1xuXG4vKipcbiAqIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIGJlZm9yZSB0aGUgb2ZmaWNpYWwgZXhwaXJhdGlvbiB0aW1lIG9mIGEgdG9rZW5cbiAqIHRvIHJlZnJlc2ggdGhhdCB0b2tlbiwgdG8gcHJvdmlkZSBhIGJ1ZmZlciBmb3IgUlBDcyB0byBjb21wbGV0ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGVudW0gQnVmZmVyIHtcbiAgVE9LRU5fUkVGUkVTSCA9IDMwXzAwMFxufVxuXG4vKipcbiAqIFdlIG5lZWQgdG8gbWFyayB0aGlzIGNsYXNzIGFzIGludGVybmFsIGV4cGxpY2l0bHkgdG8gZXhjbHVkZSBpdCBpbiB0aGUgcHVibGljIHR5cGluZ3MsIGJlY2F1c2VcbiAqIGl0IHJlZmVyZW5jZXMgQXV0aEludGVybmFsIHdoaWNoIGhhcyBhIGNpcmN1bGFyIGRlcGVuZGVuY3kgd2l0aCBVc2VySW50ZXJuYWwuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBTdHNUb2tlbk1hbmFnZXIge1xuICByZWZyZXNoVG9rZW46IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBhY2Nlc3NUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGV4cGlyYXRpb25UaW1lOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICBnZXQgaXNFeHBpcmVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICAhdGhpcy5leHBpcmF0aW9uVGltZSB8fFxuICAgICAgRGF0ZS5ub3coKSA+IHRoaXMuZXhwaXJhdGlvblRpbWUgLSBCdWZmZXIuVE9LRU5fUkVGUkVTSFxuICAgICk7XG4gIH1cblxuICB1cGRhdGVGcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgcmVzcG9uc2U6IElkVG9rZW5SZXNwb25zZSB8IEZpbmFsaXplTWZhUmVzcG9uc2VcbiAgKTogdm9pZCB7XG4gICAgX2Fzc2VydChyZXNwb25zZS5pZFRva2VuLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICBfYXNzZXJ0KFxuICAgICAgdHlwZW9mIHJlc3BvbnNlLmlkVG9rZW4gIT09ICd1bmRlZmluZWQnLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiByZXNwb25zZS5yZWZyZXNoVG9rZW4gIT09ICd1bmRlZmluZWQnLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgY29uc3QgZXhwaXJlc0luID1cbiAgICAgICdleHBpcmVzSW4nIGluIHJlc3BvbnNlICYmIHR5cGVvZiByZXNwb25zZS5leHBpcmVzSW4gIT09ICd1bmRlZmluZWQnXG4gICAgICAgID8gTnVtYmVyKHJlc3BvbnNlLmV4cGlyZXNJbilcbiAgICAgICAgOiBfdG9rZW5FeHBpcmVzSW4ocmVzcG9uc2UuaWRUb2tlbik7XG4gICAgdGhpcy51cGRhdGVUb2tlbnNBbmRFeHBpcmF0aW9uKFxuICAgICAgcmVzcG9uc2UuaWRUb2tlbixcbiAgICAgIHJlc3BvbnNlLnJlZnJlc2hUb2tlbixcbiAgICAgIGV4cGlyZXNJblxuICAgICk7XG4gIH1cblxuICB1cGRhdGVGcm9tSWRUb2tlbihpZFRva2VuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBfYXNzZXJ0KGlkVG9rZW4ubGVuZ3RoICE9PSAwLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICBjb25zdCBleHBpcmVzSW4gPSBfdG9rZW5FeHBpcmVzSW4oaWRUb2tlbik7XG4gICAgdGhpcy51cGRhdGVUb2tlbnNBbmRFeHBpcmF0aW9uKGlkVG9rZW4sIG51bGwsIGV4cGlyZXNJbik7XG4gIH1cblxuICBhc3luYyBnZXRUb2tlbihcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgZm9yY2VSZWZyZXNoID0gZmFsc2VcbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgaWYgKCFmb3JjZVJlZnJlc2ggJiYgdGhpcy5hY2Nlc3NUb2tlbiAmJiAhdGhpcy5pc0V4cGlyZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmFjY2Vzc1Rva2VuO1xuICAgIH1cblxuICAgIF9hc3NlcnQodGhpcy5yZWZyZXNoVG9rZW4sIGF1dGgsIEF1dGhFcnJvckNvZGUuVE9LRU5fRVhQSVJFRCk7XG5cbiAgICBpZiAodGhpcy5yZWZyZXNoVG9rZW4pIHtcbiAgICAgIGF3YWl0IHRoaXMucmVmcmVzaChhdXRoLCB0aGlzLnJlZnJlc2hUb2tlbiEpO1xuICAgICAgcmV0dXJuIHRoaXMuYWNjZXNzVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjbGVhclJlZnJlc2hUb2tlbigpOiB2b2lkIHtcbiAgICB0aGlzLnJlZnJlc2hUb2tlbiA9IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZnJlc2goYXV0aDogQXV0aEludGVybmFsLCBvbGRUb2tlbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBhY2Nlc3NUb2tlbiwgcmVmcmVzaFRva2VuLCBleHBpcmVzSW4gfSA9IGF3YWl0IHJlcXVlc3RTdHNUb2tlbihcbiAgICAgIGF1dGgsXG4gICAgICBvbGRUb2tlblxuICAgICk7XG4gICAgdGhpcy51cGRhdGVUb2tlbnNBbmRFeHBpcmF0aW9uKFxuICAgICAgYWNjZXNzVG9rZW4sXG4gICAgICByZWZyZXNoVG9rZW4sXG4gICAgICBOdW1iZXIoZXhwaXJlc0luKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVRva2Vuc0FuZEV4cGlyYXRpb24oXG4gICAgYWNjZXNzVG9rZW46IHN0cmluZyxcbiAgICByZWZyZXNoVG9rZW46IHN0cmluZyB8IG51bGwsXG4gICAgZXhwaXJlc0luU2VjOiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5yZWZyZXNoVG9rZW4gPSByZWZyZXNoVG9rZW4gfHwgbnVsbDtcbiAgICB0aGlzLmFjY2Vzc1Rva2VuID0gYWNjZXNzVG9rZW4gfHwgbnVsbDtcbiAgICB0aGlzLmV4cGlyYXRpb25UaW1lID0gRGF0ZS5ub3coKSArIGV4cGlyZXNJblNlYyAqIDEwMDA7XG4gIH1cblxuICBzdGF0aWMgZnJvbUpTT04oYXBwTmFtZTogc3RyaW5nLCBvYmplY3Q6IFBlcnNpc3RlZEJsb2IpOiBTdHNUb2tlbk1hbmFnZXIge1xuICAgIGNvbnN0IHsgcmVmcmVzaFRva2VuLCBhY2Nlc3NUb2tlbiwgZXhwaXJhdGlvblRpbWUgfSA9IG9iamVjdDtcblxuICAgIGNvbnN0IG1hbmFnZXIgPSBuZXcgU3RzVG9rZW5NYW5hZ2VyKCk7XG4gICAgaWYgKHJlZnJlc2hUb2tlbikge1xuICAgICAgX2Fzc2VydCh0eXBlb2YgcmVmcmVzaFRva2VuID09PSAnc3RyaW5nJywgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUiwge1xuICAgICAgICBhcHBOYW1lXG4gICAgICB9KTtcbiAgICAgIG1hbmFnZXIucmVmcmVzaFRva2VuID0gcmVmcmVzaFRva2VuO1xuICAgIH1cbiAgICBpZiAoYWNjZXNzVG9rZW4pIHtcbiAgICAgIF9hc3NlcnQodHlwZW9mIGFjY2Vzc1Rva2VuID09PSAnc3RyaW5nJywgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUiwge1xuICAgICAgICBhcHBOYW1lXG4gICAgICB9KTtcbiAgICAgIG1hbmFnZXIuYWNjZXNzVG9rZW4gPSBhY2Nlc3NUb2tlbjtcbiAgICB9XG4gICAgaWYgKGV4cGlyYXRpb25UaW1lKSB7XG4gICAgICBfYXNzZXJ0KFxuICAgICAgICB0eXBlb2YgZXhwaXJhdGlvblRpbWUgPT09ICdudW1iZXInLFxuICAgICAgICBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuICAgICAgICB7XG4gICAgICAgICAgYXBwTmFtZVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgbWFuYWdlci5leHBpcmF0aW9uVGltZSA9IGV4cGlyYXRpb25UaW1lO1xuICAgIH1cbiAgICByZXR1cm4gbWFuYWdlcjtcbiAgfVxuXG4gIHRvSlNPTigpOiBvYmplY3Qge1xuICAgIHJldHVybiB7XG4gICAgICByZWZyZXNoVG9rZW46IHRoaXMucmVmcmVzaFRva2VuLFxuICAgICAgYWNjZXNzVG9rZW46IHRoaXMuYWNjZXNzVG9rZW4sXG4gICAgICBleHBpcmF0aW9uVGltZTogdGhpcy5leHBpcmF0aW9uVGltZVxuICAgIH07XG4gIH1cblxuICBfYXNzaWduKHN0c1Rva2VuTWFuYWdlcjogU3RzVG9rZW5NYW5hZ2VyKTogdm9pZCB7XG4gICAgdGhpcy5hY2Nlc3NUb2tlbiA9IHN0c1Rva2VuTWFuYWdlci5hY2Nlc3NUb2tlbjtcbiAgICB0aGlzLnJlZnJlc2hUb2tlbiA9IHN0c1Rva2VuTWFuYWdlci5yZWZyZXNoVG9rZW47XG4gICAgdGhpcy5leHBpcmF0aW9uVGltZSA9IHN0c1Rva2VuTWFuYWdlci5leHBpcmF0aW9uVGltZTtcbiAgfVxuXG4gIF9jbG9uZSgpOiBTdHNUb2tlbk1hbmFnZXIge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBTdHNUb2tlbk1hbmFnZXIoKSwgdGhpcy50b0pTT04oKSk7XG4gIH1cblxuICBfcGVyZm9ybVJlZnJlc2goKTogbmV2ZXIge1xuICAgIHJldHVybiBkZWJ1Z0ZhaWwoJ25vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgSWRUb2tlblJlc3VsdCwgVXNlckluZm8gfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgTmV4dEZuIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHtcbiAgQVBJVXNlckluZm8sXG4gIEdldEFjY291bnRJbmZvUmVzcG9uc2UsXG4gIGRlbGV0ZUFjY291bnRcbn0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IEZpbmFsaXplTWZhUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHtcbiAgTXV0YWJsZVVzZXJJbmZvLFxuICBVc2VySW50ZXJuYWwsXG4gIFVzZXJQYXJhbWV0ZXJzXG59IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBQZXJzaXN0ZWRCbG9iIH0gZnJvbSAnLi4vcGVyc2lzdGVuY2UnO1xuaW1wb3J0IHtcbiAgX2Fzc2VydCxcbiAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3Jcbn0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgZ2V0SWRUb2tlblJlc3VsdCB9IGZyb20gJy4vaWRfdG9rZW5fcmVzdWx0JztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgUHJvYWN0aXZlUmVmcmVzaCB9IGZyb20gJy4vcHJvYWN0aXZlX3JlZnJlc2gnO1xuaW1wb3J0IHsgZXh0cmFjdFByb3ZpZGVyRGF0YSwgX3JlbG9hZFdpdGhvdXRTYXZpbmcsIHJlbG9hZCB9IGZyb20gJy4vcmVsb2FkJztcbmltcG9ydCB7IFN0c1Rva2VuTWFuYWdlciB9IGZyb20gJy4vdG9rZW5fbWFuYWdlcic7XG5pbXBvcnQgeyBVc2VyTWV0YWRhdGEgfSBmcm9tICcuL3VzZXJfbWV0YWRhdGEnO1xuaW1wb3J0IHsgUHJvdmlkZXJJZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5cbmZ1bmN0aW9uIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKFxuICBhc3NlcnRpb246IHVua25vd24sXG4gIGFwcE5hbWU6IHN0cmluZ1xuKTogYXNzZXJ0cyBhc3NlcnRpb24gaXMgc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgX2Fzc2VydChcbiAgICB0eXBlb2YgYXNzZXJ0aW9uID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgYXNzZXJ0aW9uID09PSAndW5kZWZpbmVkJyxcbiAgICBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SLFxuICAgIHsgYXBwTmFtZSB9XG4gICk7XG59XG5cbmV4cG9ydCBjbGFzcyBVc2VySW1wbCBpbXBsZW1lbnRzIFVzZXJJbnRlcm5hbCB7XG4gIC8vIEZvciB0aGUgdXNlciBvYmplY3QsIHByb3ZpZGVyIGlzIGFsd2F5cyBGaXJlYmFzZS5cbiAgcmVhZG9ubHkgcHJvdmlkZXJJZCA9IFByb3ZpZGVySWQuRklSRUJBU0U7XG4gIHN0c1Rva2VuTWFuYWdlcjogU3RzVG9rZW5NYW5hZ2VyO1xuICAvLyBMYXN0IGtub3duIGFjY2Vzc1Rva2VuIHNvIHdlIGtub3cgd2hlbiBpdCBjaGFuZ2VzXG4gIHByaXZhdGUgYWNjZXNzVG9rZW46IHN0cmluZyB8IG51bGw7XG5cbiAgdWlkOiBzdHJpbmc7XG4gIGF1dGg6IEF1dGhJbnRlcm5hbDtcbiAgZW1haWxWZXJpZmllZDogYm9vbGVhbjtcbiAgaXNBbm9ueW1vdXM6IGJvb2xlYW47XG4gIHRlbmFudElkOiBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBtZXRhZGF0YTogVXNlck1ldGFkYXRhO1xuICBwcm92aWRlckRhdGE6IE11dGFibGVVc2VySW5mb1tdO1xuXG4gIC8vIE9wdGlvbmFsIGZpZWxkcyBmcm9tIFVzZXJJbmZvXG4gIGRpc3BsYXlOYW1lOiBzdHJpbmcgfCBudWxsO1xuICBlbWFpbDogc3RyaW5nIHwgbnVsbDtcbiAgcGhvbmVOdW1iZXI6IHN0cmluZyB8IG51bGw7XG4gIHBob3RvVVJMOiBzdHJpbmcgfCBudWxsO1xuXG4gIF9yZWRpcmVjdEV2ZW50SWQ/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvYWN0aXZlUmVmcmVzaCA9IG5ldyBQcm9hY3RpdmVSZWZyZXNoKHRoaXMpO1xuXG4gIGNvbnN0cnVjdG9yKHsgdWlkLCBhdXRoLCBzdHNUb2tlbk1hbmFnZXIsIC4uLm9wdCB9OiBVc2VyUGFyYW1ldGVycykge1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMuYXV0aCA9IGF1dGg7XG4gICAgdGhpcy5zdHNUb2tlbk1hbmFnZXIgPSBzdHNUb2tlbk1hbmFnZXI7XG4gICAgdGhpcy5hY2Nlc3NUb2tlbiA9IHN0c1Rva2VuTWFuYWdlci5hY2Nlc3NUb2tlbjtcbiAgICB0aGlzLmRpc3BsYXlOYW1lID0gb3B0LmRpc3BsYXlOYW1lIHx8IG51bGw7XG4gICAgdGhpcy5lbWFpbCA9IG9wdC5lbWFpbCB8fCBudWxsO1xuICAgIHRoaXMuZW1haWxWZXJpZmllZCA9IG9wdC5lbWFpbFZlcmlmaWVkIHx8IGZhbHNlO1xuICAgIHRoaXMucGhvbmVOdW1iZXIgPSBvcHQucGhvbmVOdW1iZXIgfHwgbnVsbDtcbiAgICB0aGlzLnBob3RvVVJMID0gb3B0LnBob3RvVVJMIHx8IG51bGw7XG4gICAgdGhpcy5pc0Fub255bW91cyA9IG9wdC5pc0Fub255bW91cyB8fCBmYWxzZTtcbiAgICB0aGlzLnRlbmFudElkID0gb3B0LnRlbmFudElkIHx8IG51bGw7XG4gICAgdGhpcy5wcm92aWRlckRhdGEgPSBvcHQucHJvdmlkZXJEYXRhID8gWy4uLm9wdC5wcm92aWRlckRhdGFdIDogW107XG4gICAgdGhpcy5tZXRhZGF0YSA9IG5ldyBVc2VyTWV0YWRhdGEoXG4gICAgICBvcHQuY3JlYXRlZEF0IHx8IHVuZGVmaW5lZCxcbiAgICAgIG9wdC5sYXN0TG9naW5BdCB8fCB1bmRlZmluZWRcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgZ2V0SWRUb2tlbihmb3JjZVJlZnJlc2g/OiBib29sZWFuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgICAgdGhpcyxcbiAgICAgIHRoaXMuc3RzVG9rZW5NYW5hZ2VyLmdldFRva2VuKHRoaXMuYXV0aCwgZm9yY2VSZWZyZXNoKVxuICAgICk7XG4gICAgX2Fzc2VydChhY2Nlc3NUb2tlbiwgdGhpcy5hdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcblxuICAgIGlmICh0aGlzLmFjY2Vzc1Rva2VuICE9PSBhY2Nlc3NUb2tlbikge1xuICAgICAgdGhpcy5hY2Nlc3NUb2tlbiA9IGFjY2Vzc1Rva2VuO1xuICAgICAgYXdhaXQgdGhpcy5hdXRoLl9wZXJzaXN0VXNlcklmQ3VycmVudCh0aGlzKTtcbiAgICAgIHRoaXMuYXV0aC5fbm90aWZ5TGlzdGVuZXJzSWZDdXJyZW50KHRoaXMpO1xuICAgIH1cblxuICAgIHJldHVybiBhY2Nlc3NUb2tlbjtcbiAgfVxuXG4gIGdldElkVG9rZW5SZXN1bHQoZm9yY2VSZWZyZXNoPzogYm9vbGVhbik6IFByb21pc2U8SWRUb2tlblJlc3VsdD4ge1xuICAgIHJldHVybiBnZXRJZFRva2VuUmVzdWx0KHRoaXMsIGZvcmNlUmVmcmVzaCk7XG4gIH1cblxuICByZWxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHJlbG9hZCh0aGlzKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVsb2FkVXNlckluZm86IEFQSVVzZXJJbmZvIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVsb2FkTGlzdGVuZXI6IE5leHRGbjxBUElVc2VySW5mbz4gfCBudWxsID0gbnVsbDtcblxuICBfYXNzaWduKHVzZXI6IFVzZXJJbnRlcm5hbCk6IHZvaWQge1xuICAgIGlmICh0aGlzID09PSB1c2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIF9hc3NlcnQodGhpcy51aWQgPT09IHVzZXIudWlkLCB0aGlzLmF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIHRoaXMuZGlzcGxheU5hbWUgPSB1c2VyLmRpc3BsYXlOYW1lO1xuICAgIHRoaXMucGhvdG9VUkwgPSB1c2VyLnBob3RvVVJMO1xuICAgIHRoaXMuZW1haWwgPSB1c2VyLmVtYWlsO1xuICAgIHRoaXMuZW1haWxWZXJpZmllZCA9IHVzZXIuZW1haWxWZXJpZmllZDtcbiAgICB0aGlzLnBob25lTnVtYmVyID0gdXNlci5waG9uZU51bWJlcjtcbiAgICB0aGlzLmlzQW5vbnltb3VzID0gdXNlci5pc0Fub255bW91cztcbiAgICB0aGlzLnRlbmFudElkID0gdXNlci50ZW5hbnRJZDtcbiAgICB0aGlzLnByb3ZpZGVyRGF0YSA9IHVzZXIucHJvdmlkZXJEYXRhLm1hcCh1c2VySW5mbyA9PiAoeyAuLi51c2VySW5mbyB9KSk7XG4gICAgdGhpcy5tZXRhZGF0YS5fY29weSh1c2VyLm1ldGFkYXRhKTtcbiAgICB0aGlzLnN0c1Rva2VuTWFuYWdlci5fYXNzaWduKHVzZXIuc3RzVG9rZW5NYW5hZ2VyKTtcbiAgfVxuXG4gIF9jbG9uZShhdXRoOiBBdXRoSW50ZXJuYWwpOiBVc2VySW50ZXJuYWwge1xuICAgIGNvbnN0IG5ld1VzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgLi4udGhpcyxcbiAgICAgIGF1dGgsXG4gICAgICBzdHNUb2tlbk1hbmFnZXI6IHRoaXMuc3RzVG9rZW5NYW5hZ2VyLl9jbG9uZSgpXG4gICAgfSk7XG4gICAgbmV3VXNlci5tZXRhZGF0YS5fY29weSh0aGlzLm1ldGFkYXRhKTtcbiAgICByZXR1cm4gbmV3VXNlcjtcbiAgfVxuXG4gIF9vblJlbG9hZChjYWxsYmFjazogTmV4dEZuPEFQSVVzZXJJbmZvPik6IHZvaWQge1xuICAgIC8vIFRoZXJlIHNob3VsZCBvbmx5IGV2ZXIgYmUgb25lIGxpc3RlbmVyLCBhbmQgdGhhdCBpcyBhIHNpbmdsZSBpbnN0YW5jZSBvZiBNdWx0aUZhY3RvclVzZXJcbiAgICBfYXNzZXJ0KCF0aGlzLnJlbG9hZExpc3RlbmVyLCB0aGlzLmF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIHRoaXMucmVsb2FkTGlzdGVuZXIgPSBjYWxsYmFjaztcbiAgICBpZiAodGhpcy5yZWxvYWRVc2VySW5mbykge1xuICAgICAgdGhpcy5fbm90aWZ5UmVsb2FkTGlzdGVuZXIodGhpcy5yZWxvYWRVc2VySW5mbyk7XG4gICAgICB0aGlzLnJlbG9hZFVzZXJJbmZvID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBfbm90aWZ5UmVsb2FkTGlzdGVuZXIodXNlckluZm86IEFQSVVzZXJJbmZvKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVsb2FkTGlzdGVuZXIpIHtcbiAgICAgIHRoaXMucmVsb2FkTGlzdGVuZXIodXNlckluZm8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiBubyBsaXN0ZW5lciBpcyBzdWJzY3JpYmVkIHlldCwgc2F2ZSB0aGUgcmVzdWx0IHNvIGl0J3MgYXZhaWxhYmxlIHdoZW4gdGhleSBkbyBzdWJzY3JpYmVcbiAgICAgIHRoaXMucmVsb2FkVXNlckluZm8gPSB1c2VySW5mbztcbiAgICB9XG4gIH1cblxuICBfc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMucHJvYWN0aXZlUmVmcmVzaC5fc3RhcnQoKTtcbiAgfVxuXG4gIF9zdG9wUHJvYWN0aXZlUmVmcmVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLnByb2FjdGl2ZVJlZnJlc2guX3N0b3AoKTtcbiAgfVxuXG4gIGFzeW5jIF91cGRhdGVUb2tlbnNJZk5lY2Vzc2FyeShcbiAgICByZXNwb25zZTogSWRUb2tlblJlc3BvbnNlIHwgRmluYWxpemVNZmFSZXNwb25zZSxcbiAgICByZWxvYWQgPSBmYWxzZVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgdG9rZW5zUmVmcmVzaGVkID0gZmFsc2U7XG4gICAgaWYgKFxuICAgICAgcmVzcG9uc2UuaWRUb2tlbiAmJlxuICAgICAgcmVzcG9uc2UuaWRUb2tlbiAhPT0gdGhpcy5zdHNUb2tlbk1hbmFnZXIuYWNjZXNzVG9rZW5cbiAgICApIHtcbiAgICAgIHRoaXMuc3RzVG9rZW5NYW5hZ2VyLnVwZGF0ZUZyb21TZXJ2ZXJSZXNwb25zZShyZXNwb25zZSk7XG4gICAgICB0b2tlbnNSZWZyZXNoZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChyZWxvYWQpIHtcbiAgICAgIGF3YWl0IF9yZWxvYWRXaXRob3V0U2F2aW5nKHRoaXMpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuYXV0aC5fcGVyc2lzdFVzZXJJZkN1cnJlbnQodGhpcyk7XG4gICAgaWYgKHRva2Vuc1JlZnJlc2hlZCkge1xuICAgICAgdGhpcy5hdXRoLl9ub3RpZnlMaXN0ZW5lcnNJZkN1cnJlbnQodGhpcyk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZGVsZXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmF1dGguYXBwKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcih0aGlzLmF1dGgpXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBpZFRva2VuID0gYXdhaXQgdGhpcy5nZXRJZFRva2VuKCk7XG4gICAgYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQodGhpcywgZGVsZXRlQWNjb3VudCh0aGlzLmF1dGgsIHsgaWRUb2tlbiB9KSk7XG4gICAgdGhpcy5zdHNUb2tlbk1hbmFnZXIuY2xlYXJSZWZyZXNoVG9rZW4oKTtcblxuICAgIC8vIFRPRE86IERldGVybWluZSBpZiBjYW5jZWxsYWJsZS1wcm9taXNlcyBhcmUgbmVjZXNzYXJ5IHRvIHVzZSBpbiB0aGlzIGNsYXNzIHNvIHRoYXQgZGVsZXRlKClcbiAgICAvLyAgICAgICBjYW5jZWxzIHBlbmRpbmcgYWN0aW9ucy4uLlxuXG4gICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduT3V0KCk7XG4gIH1cblxuICB0b0pTT04oKTogUGVyc2lzdGVkQmxvYiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVpZDogdGhpcy51aWQsXG4gICAgICBlbWFpbDogdGhpcy5lbWFpbCB8fCB1bmRlZmluZWQsXG4gICAgICBlbWFpbFZlcmlmaWVkOiB0aGlzLmVtYWlsVmVyaWZpZWQsXG4gICAgICBkaXNwbGF5TmFtZTogdGhpcy5kaXNwbGF5TmFtZSB8fCB1bmRlZmluZWQsXG4gICAgICBpc0Fub255bW91czogdGhpcy5pc0Fub255bW91cyxcbiAgICAgIHBob3RvVVJMOiB0aGlzLnBob3RvVVJMIHx8IHVuZGVmaW5lZCxcbiAgICAgIHBob25lTnVtYmVyOiB0aGlzLnBob25lTnVtYmVyIHx8IHVuZGVmaW5lZCxcbiAgICAgIHRlbmFudElkOiB0aGlzLnRlbmFudElkIHx8IHVuZGVmaW5lZCxcbiAgICAgIHByb3ZpZGVyRGF0YTogdGhpcy5wcm92aWRlckRhdGEubWFwKHVzZXJJbmZvID0+ICh7IC4uLnVzZXJJbmZvIH0pKSxcbiAgICAgIHN0c1Rva2VuTWFuYWdlcjogdGhpcy5zdHNUb2tlbk1hbmFnZXIudG9KU09OKCksXG4gICAgICAvLyBSZWRpcmVjdCBldmVudCBJRCBtdXN0IGJlIG1haW50YWluZWQgaW4gY2FzZSB0aGVyZSBpcyBhIHBlbmRpbmdcbiAgICAgIC8vIHJlZGlyZWN0IGV2ZW50LlxuICAgICAgX3JlZGlyZWN0RXZlbnRJZDogdGhpcy5fcmVkaXJlY3RFdmVudElkLFxuICAgICAgLi4udGhpcy5tZXRhZGF0YS50b0pTT04oKSxcblxuICAgICAgLy8gUmVxdWlyZWQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCB0aGUgbGVnYWN5IFNESyAoZ28vZmlyZWJhc2UtYXV0aC1zZGstcGVyc2lzdGVuY2UtcGFyc2luZyk6XG4gICAgICBhcGlLZXk6IHRoaXMuYXV0aC5jb25maWcuYXBpS2V5LFxuICAgICAgYXBwTmFtZTogdGhpcy5hdXRoLm5hbWVcbiAgICAgIC8vIE1pc3NpbmcgYXV0aERvbWFpbiB3aWxsIGJlIHRvbGVyYXRlZCBieSB0aGUgbGVnYWN5IFNESy5cbiAgICAgIC8vIHN0c1Rva2VuTWFuYWdlci5hcGlLZXkgaXNuJ3QgYWN0dWFsbHkgcmVxdWlyZWQgKGRlc3BpdGUgdGhlIGxlZ2FjeSBTREsgcGVyc2lzdGluZyBpdCkuXG4gICAgfTtcbiAgfVxuXG4gIGdldCByZWZyZXNoVG9rZW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zdHNUb2tlbk1hbmFnZXIucmVmcmVzaFRva2VuIHx8ICcnO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tSlNPTihhdXRoOiBBdXRoSW50ZXJuYWwsIG9iamVjdDogUGVyc2lzdGVkQmxvYik6IFVzZXJJbnRlcm5hbCB7XG4gICAgY29uc3QgZGlzcGxheU5hbWUgPSBvYmplY3QuZGlzcGxheU5hbWUgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGVtYWlsID0gb2JqZWN0LmVtYWlsID8/IHVuZGVmaW5lZDtcbiAgICBjb25zdCBwaG9uZU51bWJlciA9IG9iamVjdC5waG9uZU51bWJlciA/PyB1bmRlZmluZWQ7XG4gICAgY29uc3QgcGhvdG9VUkwgPSBvYmplY3QucGhvdG9VUkwgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRlbmFudElkID0gb2JqZWN0LnRlbmFudElkID8/IHVuZGVmaW5lZDtcbiAgICBjb25zdCBfcmVkaXJlY3RFdmVudElkID0gb2JqZWN0Ll9yZWRpcmVjdEV2ZW50SWQgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGNyZWF0ZWRBdCA9IG9iamVjdC5jcmVhdGVkQXQgPz8gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGxhc3RMb2dpbkF0ID0gb2JqZWN0Lmxhc3RMb2dpbkF0ID8/IHVuZGVmaW5lZDtcbiAgICBjb25zdCB7XG4gICAgICB1aWQsXG4gICAgICBlbWFpbFZlcmlmaWVkLFxuICAgICAgaXNBbm9ueW1vdXMsXG4gICAgICBwcm92aWRlckRhdGEsXG4gICAgICBzdHNUb2tlbk1hbmFnZXI6IHBsYWluT2JqZWN0VG9rZW5NYW5hZ2VyXG4gICAgfSA9IG9iamVjdDtcblxuICAgIF9hc3NlcnQodWlkICYmIHBsYWluT2JqZWN0VG9rZW5NYW5hZ2VyLCBhdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcblxuICAgIGNvbnN0IHN0c1Rva2VuTWFuYWdlciA9IFN0c1Rva2VuTWFuYWdlci5mcm9tSlNPTihcbiAgICAgIHRoaXMubmFtZSxcbiAgICAgIHBsYWluT2JqZWN0VG9rZW5NYW5hZ2VyIGFzIFBlcnNpc3RlZEJsb2JcbiAgICApO1xuXG4gICAgX2Fzc2VydCh0eXBlb2YgdWlkID09PSAnc3RyaW5nJywgYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgYXNzZXJ0U3RyaW5nT3JVbmRlZmluZWQoZGlzcGxheU5hbWUsIGF1dGgubmFtZSk7XG4gICAgYXNzZXJ0U3RyaW5nT3JVbmRlZmluZWQoZW1haWwsIGF1dGgubmFtZSk7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiBlbWFpbFZlcmlmaWVkID09PSAnYm9vbGVhbicsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiBpc0Fub255bW91cyA9PT0gJ2Jvb2xlYW4nLFxuICAgICAgYXV0aCxcbiAgICAgIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1JcbiAgICApO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKHBob25lTnVtYmVyLCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKHBob3RvVVJMLCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKHRlbmFudElkLCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKF9yZWRpcmVjdEV2ZW50SWQsIGF1dGgubmFtZSk7XG4gICAgYXNzZXJ0U3RyaW5nT3JVbmRlZmluZWQoY3JlYXRlZEF0LCBhdXRoLm5hbWUpO1xuICAgIGFzc2VydFN0cmluZ09yVW5kZWZpbmVkKGxhc3RMb2dpbkF0LCBhdXRoLm5hbWUpO1xuICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgdWlkLFxuICAgICAgYXV0aCxcbiAgICAgIGVtYWlsLFxuICAgICAgZW1haWxWZXJpZmllZCxcbiAgICAgIGRpc3BsYXlOYW1lLFxuICAgICAgaXNBbm9ueW1vdXMsXG4gICAgICBwaG90b1VSTCxcbiAgICAgIHBob25lTnVtYmVyLFxuICAgICAgdGVuYW50SWQsXG4gICAgICBzdHNUb2tlbk1hbmFnZXIsXG4gICAgICBjcmVhdGVkQXQsXG4gICAgICBsYXN0TG9naW5BdFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3ZpZGVyRGF0YSAmJiBBcnJheS5pc0FycmF5KHByb3ZpZGVyRGF0YSkpIHtcbiAgICAgIHVzZXIucHJvdmlkZXJEYXRhID0gcHJvdmlkZXJEYXRhLm1hcCh1c2VySW5mbyA9PiAoeyAuLi51c2VySW5mbyB9KSk7XG4gICAgfVxuXG4gICAgaWYgKF9yZWRpcmVjdEV2ZW50SWQpIHtcbiAgICAgIHVzZXIuX3JlZGlyZWN0RXZlbnRJZCA9IF9yZWRpcmVjdEV2ZW50SWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVzZXI7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBhIFVzZXIgZnJvbSBhbiBpZFRva2VuIHNlcnZlciByZXNwb25zZVxuICAgKiBAcGFyYW0gYXV0aFxuICAgKiBAcGFyYW0gaWRUb2tlblJlc3BvbnNlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgX2Zyb21JZFRva2VuUmVzcG9uc2UoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGlkVG9rZW5SZXNwb25zZTogSWRUb2tlblJlc3BvbnNlLFxuICAgIGlzQW5vbnltb3VzOiBib29sZWFuID0gZmFsc2VcbiAgKTogUHJvbWlzZTxVc2VySW50ZXJuYWw+IHtcbiAgICBjb25zdCBzdHNUb2tlbk1hbmFnZXIgPSBuZXcgU3RzVG9rZW5NYW5hZ2VyKCk7XG4gICAgc3RzVG9rZW5NYW5hZ2VyLnVwZGF0ZUZyb21TZXJ2ZXJSZXNwb25zZShpZFRva2VuUmVzcG9uc2UpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgRmlyZWJhc2UgQXV0aCB1c2VyLlxuICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgdWlkOiBpZFRva2VuUmVzcG9uc2UubG9jYWxJZCxcbiAgICAgIGF1dGgsXG4gICAgICBzdHNUb2tlbk1hbmFnZXIsXG4gICAgICBpc0Fub255bW91c1xuICAgIH0pO1xuXG4gICAgLy8gVXBkYXRlcyB0aGUgdXNlciBpbmZvIGFuZCBkYXRhIGFuZCByZXNvbHZlcyB3aXRoIGEgdXNlciBpbnN0YW5jZS5cbiAgICBhd2FpdCBfcmVsb2FkV2l0aG91dFNhdmluZyh1c2VyKTtcbiAgICByZXR1cm4gdXNlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGEgVXNlciBmcm9tIGFuIGlkVG9rZW4gc2VydmVyIHJlc3BvbnNlXG4gICAqIEBwYXJhbSBhdXRoXG4gICAqIEBwYXJhbSBpZFRva2VuUmVzcG9uc2VcbiAgICovXG4gIHN0YXRpYyBhc3luYyBfZnJvbUdldEFjY291bnRJbmZvUmVzcG9uc2UoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIHJlc3BvbnNlOiBHZXRBY2NvdW50SW5mb1Jlc3BvbnNlLFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPFVzZXJJbnRlcm5hbD4ge1xuICAgIGNvbnN0IGNvcmVBY2NvdW50ID0gcmVzcG9uc2UudXNlcnNbMF07XG4gICAgX2Fzc2VydChjb3JlQWNjb3VudC5sb2NhbElkICE9PSB1bmRlZmluZWQsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuXG4gICAgY29uc3QgcHJvdmlkZXJEYXRhOiBVc2VySW5mb1tdID1cbiAgICAgIGNvcmVBY2NvdW50LnByb3ZpZGVyVXNlckluZm8gIT09IHVuZGVmaW5lZFxuICAgICAgICA/IGV4dHJhY3RQcm92aWRlckRhdGEoY29yZUFjY291bnQucHJvdmlkZXJVc2VySW5mbylcbiAgICAgICAgOiBbXTtcblxuICAgIGNvbnN0IGlzQW5vbnltb3VzID1cbiAgICAgICEoY29yZUFjY291bnQuZW1haWwgJiYgY29yZUFjY291bnQucGFzc3dvcmRIYXNoKSAmJiAhcHJvdmlkZXJEYXRhPy5sZW5ndGg7XG5cbiAgICBjb25zdCBzdHNUb2tlbk1hbmFnZXIgPSBuZXcgU3RzVG9rZW5NYW5hZ2VyKCk7XG4gICAgc3RzVG9rZW5NYW5hZ2VyLnVwZGF0ZUZyb21JZFRva2VuKGlkVG9rZW4pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgRmlyZWJhc2UgQXV0aCB1c2VyLlxuICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlckltcGwoe1xuICAgICAgdWlkOiBjb3JlQWNjb3VudC5sb2NhbElkLFxuICAgICAgYXV0aCxcbiAgICAgIHN0c1Rva2VuTWFuYWdlcixcbiAgICAgIGlzQW5vbnltb3VzXG4gICAgfSk7XG5cbiAgICAvLyB1cGRhdGUgdGhlIHVzZXIgd2l0aCBkYXRhIGZyb20gdGhlIEdldEFjY291bnRJbmZvIHJlc3BvbnNlLlxuICAgIGNvbnN0IHVwZGF0ZXM6IFBhcnRpYWw8VXNlckludGVybmFsPiA9IHtcbiAgICAgIHVpZDogY29yZUFjY291bnQubG9jYWxJZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBjb3JlQWNjb3VudC5kaXNwbGF5TmFtZSB8fCBudWxsLFxuICAgICAgcGhvdG9VUkw6IGNvcmVBY2NvdW50LnBob3RvVXJsIHx8IG51bGwsXG4gICAgICBlbWFpbDogY29yZUFjY291bnQuZW1haWwgfHwgbnVsbCxcbiAgICAgIGVtYWlsVmVyaWZpZWQ6IGNvcmVBY2NvdW50LmVtYWlsVmVyaWZpZWQgfHwgZmFsc2UsXG4gICAgICBwaG9uZU51bWJlcjogY29yZUFjY291bnQucGhvbmVOdW1iZXIgfHwgbnVsbCxcbiAgICAgIHRlbmFudElkOiBjb3JlQWNjb3VudC50ZW5hbnRJZCB8fCBudWxsLFxuICAgICAgcHJvdmlkZXJEYXRhLFxuICAgICAgbWV0YWRhdGE6IG5ldyBVc2VyTWV0YWRhdGEoXG4gICAgICAgIGNvcmVBY2NvdW50LmNyZWF0ZWRBdCxcbiAgICAgICAgY29yZUFjY291bnQubGFzdExvZ2luQXRcbiAgICAgICksXG4gICAgICBpc0Fub255bW91czpcbiAgICAgICAgIShjb3JlQWNjb3VudC5lbWFpbCAmJiBjb3JlQWNjb3VudC5wYXNzd29yZEhhc2gpICYmXG4gICAgICAgICFwcm92aWRlckRhdGE/Lmxlbmd0aFxuICAgIH07XG5cbiAgICBPYmplY3QuYXNzaWduKHVzZXIsIHVwZGF0ZXMpO1xuICAgIHJldHVybiB1c2VyO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgZGVidWdBc3NlcnQgfSBmcm9tICcuL2Fzc2VydCc7XG5cbi8qKlxuICogT3VyIEFQSSBoYXMgYSBsb3Qgb2Ygb25lLW9mZiBjb25zdGFudHMgdGhhdCBhcmUgdXNlZCB0byBkbyB0aGluZ3MuXG4gKiBVbmZvcnR1bmF0ZWx5IHdlIGNhbid0IGV4cG9ydCB0aGVzZSBhcyBjbGFzc2VzIGluc3RhbnRpYXRlZCBkaXJlY3RseSBzaW5jZVxuICogdGhlIGNvbnN0cnVjdG9yIG1heSBzaWRlIGVmZmVjdCBhbmQgdGhlcmVmb3JlIGNhbid0IGJlIHByb3ZlbiB0byBiZSBzYWZlbHlcbiAqIGN1bGxlZC4gSW5zdGVhZCwgd2UgZXhwb3J0IHRoZXNlIGNsYXNzZXMgdGhlbXNlbHZlcyBhcyBhIGxvd2VyQ2FtZWxDYXNlXG4gKiBjb25zdGFudCwgYW5kIGluc3RhbnRpYXRlIHRoZW0gdW5kZXIgdGhlIGhvb2QuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2luZ2xldG9uSW5zdGFudGlhdG9yPFQ+IHtcbiAgbmV3ICgpOiBUO1xufVxuXG5jb25zdCBpbnN0YW5jZUNhY2hlOiBNYXA8dW5rbm93biwgdW5rbm93bj4gPSBuZXcgTWFwKCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBfZ2V0SW5zdGFuY2U8VD4oY2xzOiB1bmtub3duKTogVCB7XG4gIGRlYnVnQXNzZXJ0KGNscyBpbnN0YW5jZW9mIEZ1bmN0aW9uLCAnRXhwZWN0ZWQgYSBjbGFzcyBkZWZpbml0aW9uJyk7XG4gIGxldCBpbnN0YW5jZSA9IGluc3RhbmNlQ2FjaGUuZ2V0KGNscykgYXMgVCB8IHVuZGVmaW5lZDtcblxuICBpZiAoaW5zdGFuY2UpIHtcbiAgICBkZWJ1Z0Fzc2VydChcbiAgICAgIGluc3RhbmNlIGluc3RhbmNlb2YgY2xzLFxuICAgICAgJ0luc3RhbmNlIHN0b3JlZCBpbiBjYWNoZSBtaXNtYXRjaGVkIHdpdGggY2xhc3MnXG4gICAgKTtcbiAgICByZXR1cm4gaW5zdGFuY2U7XG4gIH1cblxuICBpbnN0YW5jZSA9IG5ldyAoY2xzIGFzIFNpbmdsZXRvbkluc3RhbnRpYXRvcjxUPikoKTtcbiAgaW5zdGFuY2VDYWNoZS5zZXQoY2xzLCBpbnN0YW5jZSk7XG4gIHJldHVybiBpbnN0YW5jZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9jbGVhckluc3RhbmNlTWFwKCk6IHZvaWQge1xuICBpbnN0YW5jZUNhY2hlLmNsZWFyKCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUGVyc2lzdGVuY2UgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQge1xuICBQZXJzaXN0ZW5jZUludGVybmFsLFxuICBQZXJzaXN0ZW5jZVR5cGUsXG4gIFBlcnNpc3RlbmNlVmFsdWUsXG4gIFN0b3JhZ2VFdmVudExpc3RlbmVyXG59IGZyb20gJy4uL3BlcnNpc3RlbmNlJztcblxuZXhwb3J0IGNsYXNzIEluTWVtb3J5UGVyc2lzdGVuY2UgaW1wbGVtZW50cyBQZXJzaXN0ZW5jZUludGVybmFsIHtcbiAgc3RhdGljIHR5cGU6ICdOT05FJyA9ICdOT05FJztcbiAgcmVhZG9ubHkgdHlwZSA9IFBlcnNpc3RlbmNlVHlwZS5OT05FO1xuICBzdG9yYWdlOiBSZWNvcmQ8c3RyaW5nLCBQZXJzaXN0ZW5jZVZhbHVlPiA9IHt9O1xuXG4gIGFzeW5jIF9pc0F2YWlsYWJsZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIF9zZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBQZXJzaXN0ZW5jZVZhbHVlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zdG9yYWdlW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGFzeW5jIF9nZXQ8VCBleHRlbmRzIFBlcnNpc3RlbmNlVmFsdWU+KGtleTogc3RyaW5nKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zdG9yYWdlW2tleV07XG4gICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyBudWxsIDogKHZhbHVlIGFzIFQpO1xuICB9XG5cbiAgYXN5bmMgX3JlbW92ZShrZXk6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGRlbGV0ZSB0aGlzLnN0b3JhZ2Vba2V5XTtcbiAgfVxuXG4gIF9hZGRMaXN0ZW5lcihfa2V5OiBzdHJpbmcsIF9saXN0ZW5lcjogU3RvcmFnZUV2ZW50TGlzdGVuZXIpOiB2b2lkIHtcbiAgICAvLyBMaXN0ZW5lcnMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIGluLW1lbW9yeSBzdG9yYWdlIHNpbmNlIGl0IGNhbm5vdCBiZSBzaGFyZWQgYWNyb3NzIHdpbmRvd3Mvd29ya2Vyc1xuICAgIHJldHVybjtcbiAgfVxuXG4gIF9yZW1vdmVMaXN0ZW5lcihfa2V5OiBzdHJpbmcsIF9saXN0ZW5lcjogU3RvcmFnZUV2ZW50TGlzdGVuZXIpOiB2b2lkIHtcbiAgICAvLyBMaXN0ZW5lcnMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIGluLW1lbW9yeSBzdG9yYWdlIHNpbmNlIGl0IGNhbm5vdCBiZSBzaGFyZWQgYWNyb3NzIHdpbmRvd3Mvd29ya2Vyc1xuICAgIHJldHVybjtcbiAgfVxufVxuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBQZXJzaXN0ZW5jZX0gb2YgdHlwZSAnTk9ORScuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgaW5NZW1vcnlQZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2UgPSBJbk1lbW9yeVBlcnNpc3RlbmNlO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGdldEFjY291bnRJbmZvIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IEFwaUtleSwgQXBwTmFtZSwgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IFBlcnNpc3RlZEJsb2IsIFBlcnNpc3RlbmNlSW50ZXJuYWwgfSBmcm9tICcuLi9wZXJzaXN0ZW5jZSc7XG5pbXBvcnQgeyBVc2VySW1wbCB9IGZyb20gJy4uL3VzZXIvdXNlcl9pbXBsJztcbmltcG9ydCB7IF9nZXRJbnN0YW5jZSB9IGZyb20gJy4uL3V0aWwvaW5zdGFudGlhdG9yJztcbmltcG9ydCB7IGluTWVtb3J5UGVyc2lzdGVuY2UgfSBmcm9tICcuL2luX21lbW9yeSc7XG5cbmV4cG9ydCBjb25zdCBlbnVtIEtleU5hbWUge1xuICBBVVRIX1VTRVIgPSAnYXV0aFVzZXInLFxuICBBVVRIX0VWRU5UID0gJ2F1dGhFdmVudCcsXG4gIFJFRElSRUNUX1VTRVIgPSAncmVkaXJlY3RVc2VyJyxcbiAgUEVSU0lTVEVOQ0VfVVNFUiA9ICdwZXJzaXN0ZW5jZSdcbn1cbmV4cG9ydCBjb25zdCBlbnVtIE5hbWVzcGFjZSB7XG4gIFBFUlNJU1RFTkNFID0gJ2ZpcmViYXNlJ1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3BlcnNpc3RlbmNlS2V5TmFtZShcbiAga2V5OiBzdHJpbmcsXG4gIGFwaUtleTogQXBpS2V5LFxuICBhcHBOYW1lOiBBcHBOYW1lXG4pOiBzdHJpbmcge1xuICByZXR1cm4gYCR7TmFtZXNwYWNlLlBFUlNJU1RFTkNFfToke2tleX06JHthcGlLZXl9OiR7YXBwTmFtZX1gO1xufVxuXG5leHBvcnQgY2xhc3MgUGVyc2lzdGVuY2VVc2VyTWFuYWdlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZnVsbFVzZXJLZXk6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBmdWxsUGVyc2lzdGVuY2VLZXk6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBib3VuZEV2ZW50SGFuZGxlcjogKCkgPT4gdm9pZDtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBwZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2VJbnRlcm5hbCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHVzZXJLZXk6IHN0cmluZ1xuICApIHtcbiAgICBjb25zdCB7IGNvbmZpZywgbmFtZSB9ID0gdGhpcy5hdXRoO1xuICAgIHRoaXMuZnVsbFVzZXJLZXkgPSBfcGVyc2lzdGVuY2VLZXlOYW1lKHRoaXMudXNlcktleSwgY29uZmlnLmFwaUtleSwgbmFtZSk7XG4gICAgdGhpcy5mdWxsUGVyc2lzdGVuY2VLZXkgPSBfcGVyc2lzdGVuY2VLZXlOYW1lKFxuICAgICAgS2V5TmFtZS5QRVJTSVNURU5DRV9VU0VSLFxuICAgICAgY29uZmlnLmFwaUtleSxcbiAgICAgIG5hbWVcbiAgICApO1xuICAgIHRoaXMuYm91bmRFdmVudEhhbmRsZXIgPSBhdXRoLl9vblN0b3JhZ2VFdmVudC5iaW5kKGF1dGgpO1xuICAgIHRoaXMucGVyc2lzdGVuY2UuX2FkZExpc3RlbmVyKHRoaXMuZnVsbFVzZXJLZXksIHRoaXMuYm91bmRFdmVudEhhbmRsZXIpO1xuICB9XG5cbiAgc2V0Q3VycmVudFVzZXIodXNlcjogVXNlckludGVybmFsKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMucGVyc2lzdGVuY2UuX3NldCh0aGlzLmZ1bGxVc2VyS2V5LCB1c2VyLnRvSlNPTigpKTtcbiAgfVxuXG4gIGFzeW5jIGdldEN1cnJlbnRVc2VyKCk6IFByb21pc2U8VXNlckludGVybmFsIHwgbnVsbD4ge1xuICAgIGNvbnN0IGJsb2IgPSBhd2FpdCB0aGlzLnBlcnNpc3RlbmNlLl9nZXQ8UGVyc2lzdGVkQmxvYiB8IHN0cmluZz4oXG4gICAgICB0aGlzLmZ1bGxVc2VyS2V5XG4gICAgKTtcbiAgICBpZiAoIWJsb2IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGJsb2IgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldEFjY291bnRJbmZvKHRoaXMuYXV0aCwgeyBpZFRva2VuOiBibG9iIH0pLmNhdGNoKFxuICAgICAgICAoKSA9PiB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFVzZXJJbXBsLl9mcm9tR2V0QWNjb3VudEluZm9SZXNwb25zZSh0aGlzLmF1dGgsIHJlc3BvbnNlLCBibG9iKTtcbiAgICB9XG4gICAgcmV0dXJuIFVzZXJJbXBsLl9mcm9tSlNPTih0aGlzLmF1dGgsIGJsb2IpO1xuICB9XG5cbiAgcmVtb3ZlQ3VycmVudFVzZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMucGVyc2lzdGVuY2UuX3JlbW92ZSh0aGlzLmZ1bGxVc2VyS2V5KTtcbiAgfVxuXG4gIHNhdmVQZXJzaXN0ZW5jZUZvclJlZGlyZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnBlcnNpc3RlbmNlLl9zZXQoXG4gICAgICB0aGlzLmZ1bGxQZXJzaXN0ZW5jZUtleSxcbiAgICAgIHRoaXMucGVyc2lzdGVuY2UudHlwZVxuICAgICk7XG4gIH1cblxuICBhc3luYyBzZXRQZXJzaXN0ZW5jZShuZXdQZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2VJbnRlcm5hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnBlcnNpc3RlbmNlID09PSBuZXdQZXJzaXN0ZW5jZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRVc2VyID0gYXdhaXQgdGhpcy5nZXRDdXJyZW50VXNlcigpO1xuICAgIGF3YWl0IHRoaXMucmVtb3ZlQ3VycmVudFVzZXIoKTtcblxuICAgIHRoaXMucGVyc2lzdGVuY2UgPSBuZXdQZXJzaXN0ZW5jZTtcblxuICAgIGlmIChjdXJyZW50VXNlcikge1xuICAgICAgcmV0dXJuIHRoaXMuc2V0Q3VycmVudFVzZXIoY3VycmVudFVzZXIpO1xuICAgIH1cbiAgfVxuXG4gIGRlbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnBlcnNpc3RlbmNlLl9yZW1vdmVMaXN0ZW5lcih0aGlzLmZ1bGxVc2VyS2V5LCB0aGlzLmJvdW5kRXZlbnRIYW5kbGVyKTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBjcmVhdGUoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5OiBQZXJzaXN0ZW5jZUludGVybmFsW10sXG4gICAgdXNlcktleSA9IEtleU5hbWUuQVVUSF9VU0VSXG4gICk6IFByb21pc2U8UGVyc2lzdGVuY2VVc2VyTWFuYWdlcj4ge1xuICAgIGlmICghcGVyc2lzdGVuY2VIaWVyYXJjaHkubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gbmV3IFBlcnNpc3RlbmNlVXNlck1hbmFnZXIoXG4gICAgICAgIF9nZXRJbnN0YW5jZShpbk1lbW9yeVBlcnNpc3RlbmNlKSxcbiAgICAgICAgYXV0aCxcbiAgICAgICAgdXNlcktleVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBFbGltaW5hdGUgYW55IHBlcnNpc3RlbmNlcyB0aGF0IGFyZSBub3QgYXZhaWxhYmxlXG4gICAgY29uc3QgYXZhaWxhYmxlUGVyc2lzdGVuY2VzID0gKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5Lm1hcChhc3luYyBwZXJzaXN0ZW5jZSA9PiB7XG4gICAgICAgICAgaWYgKGF3YWl0IHBlcnNpc3RlbmNlLl9pc0F2YWlsYWJsZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gcGVyc2lzdGVuY2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgKS5maWx0ZXIocGVyc2lzdGVuY2UgPT4gcGVyc2lzdGVuY2UpIGFzIFBlcnNpc3RlbmNlSW50ZXJuYWxbXTtcblxuICAgIC8vIEZhbGwgYmFjayB0byB0aGUgZmlyc3QgcGVyc2lzdGVuY2UgbGlzdGVkLCBvciBpbiBtZW1vcnkgaWYgbm9uZSBhdmFpbGFibGVcbiAgICBsZXQgc2VsZWN0ZWRQZXJzaXN0ZW5jZSA9XG4gICAgICBhdmFpbGFibGVQZXJzaXN0ZW5jZXNbMF0gfHxcbiAgICAgIF9nZXRJbnN0YW5jZTxQZXJzaXN0ZW5jZUludGVybmFsPihpbk1lbW9yeVBlcnNpc3RlbmNlKTtcblxuICAgIGNvbnN0IGtleSA9IF9wZXJzaXN0ZW5jZUtleU5hbWUodXNlcktleSwgYXV0aC5jb25maWcuYXBpS2V5LCBhdXRoLm5hbWUpO1xuXG4gICAgLy8gUHVsbCBvdXQgdGhlIGV4aXN0aW5nIHVzZXIsIHNldHRpbmcgdGhlIGNob3NlbiBwZXJzaXN0ZW5jZSB0byB0aGF0XG4gICAgLy8gcGVyc2lzdGVuY2UgaWYgdGhlIHVzZXIgZXhpc3RzLlxuICAgIGxldCB1c2VyVG9NaWdyYXRlOiBVc2VySW50ZXJuYWwgfCBudWxsID0gbnVsbDtcbiAgICAvLyBOb3RlLCBoZXJlIHdlIGNoZWNrIGZvciBhIHVzZXIgaW4gX2FsbF8gcGVyc2lzdGVuY2VzLCBub3QganVzdCB0aGVcbiAgICAvLyBvbmVzIGRlZW1lZCBhdmFpbGFibGUuIElmIHdlIGNhbiBtaWdyYXRlIGEgdXNlciBvdXQgb2YgYSBicm9rZW5cbiAgICAvLyBwZXJzaXN0ZW5jZSwgd2Ugd2lsbCAoYnV0IG9ubHkgaWYgdGhhdCBwZXJzaXN0ZW5jZSBzdXBwb3J0cyBtaWdyYXRpb24pLlxuICAgIGZvciAoY29uc3QgcGVyc2lzdGVuY2Ugb2YgcGVyc2lzdGVuY2VIaWVyYXJjaHkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGJsb2IgPSBhd2FpdCBwZXJzaXN0ZW5jZS5fZ2V0PFBlcnNpc3RlZEJsb2IgfCBzdHJpbmc+KGtleSk7XG4gICAgICAgIGlmIChibG9iKSB7XG4gICAgICAgICAgbGV0IHVzZXI6IFVzZXJJbnRlcm5hbDtcbiAgICAgICAgICBpZiAodHlwZW9mIGJsb2IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldEFjY291bnRJbmZvKGF1dGgsIHtcbiAgICAgICAgICAgICAgaWRUb2tlbjogYmxvYlxuICAgICAgICAgICAgfSkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB1c2VyID0gYXdhaXQgVXNlckltcGwuX2Zyb21HZXRBY2NvdW50SW5mb1Jlc3BvbnNlKFxuICAgICAgICAgICAgICBhdXRoLFxuICAgICAgICAgICAgICByZXNwb25zZSxcbiAgICAgICAgICAgICAgYmxvYlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXNlciA9IFVzZXJJbXBsLl9mcm9tSlNPTihhdXRoLCBibG9iKTsgLy8gdGhyb3dzIGZvciB1bnBhcnNhYmxlIGJsb2IgKHdyb25nIGZvcm1hdClcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHBlcnNpc3RlbmNlICE9PSBzZWxlY3RlZFBlcnNpc3RlbmNlKSB7XG4gICAgICAgICAgICB1c2VyVG9NaWdyYXRlID0gdXNlcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2VsZWN0ZWRQZXJzaXN0ZW5jZSA9IHBlcnNpc3RlbmNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHt9XG4gICAgfVxuXG4gICAgLy8gSWYgd2UgZmluZCB0aGUgdXNlciBpbiBhIHBlcnNpc3RlbmNlIHRoYXQgZG9lcyBzdXBwb3J0IG1pZ3JhdGlvbiwgdXNlXG4gICAgLy8gdGhhdCBtaWdyYXRpb24gcGF0aCAob2Ygb25seSBwZXJzaXN0ZW5jZXMgdGhhdCBzdXBwb3J0IG1pZ3JhdGlvbilcbiAgICBjb25zdCBtaWdyYXRpb25IaWVyYXJjaHkgPSBhdmFpbGFibGVQZXJzaXN0ZW5jZXMuZmlsdGVyKFxuICAgICAgcCA9PiBwLl9zaG91bGRBbGxvd01pZ3JhdGlvblxuICAgICk7XG5cbiAgICAvLyBJZiB0aGUgcGVyc2lzdGVuY2UgZG9lcyBfbm90XyBhbGxvdyBtaWdyYXRpb24sIGp1c3QgZmluaXNoIG9mZiBoZXJlXG4gICAgaWYgKFxuICAgICAgIXNlbGVjdGVkUGVyc2lzdGVuY2UuX3Nob3VsZEFsbG93TWlncmF0aW9uIHx8XG4gICAgICAhbWlncmF0aW9uSGllcmFyY2h5Lmxlbmd0aFxuICAgICkge1xuICAgICAgcmV0dXJuIG5ldyBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyKHNlbGVjdGVkUGVyc2lzdGVuY2UsIGF1dGgsIHVzZXJLZXkpO1xuICAgIH1cblxuICAgIHNlbGVjdGVkUGVyc2lzdGVuY2UgPSBtaWdyYXRpb25IaWVyYXJjaHlbMF07XG4gICAgaWYgKHVzZXJUb01pZ3JhdGUpIHtcbiAgICAgIC8vIFRoaXMgbm9ybWFsbHkgc2hvdWxkbid0IHRocm93IHNpbmNlIGNob3NlblBlcnNpc3RlbmNlLmlzQXZhaWxhYmxlKCkgaXMgdHJ1ZSwgYnV0IGlmIGl0IGRvZXNcbiAgICAgIC8vIHdlJ2xsIGp1c3QgbGV0IGl0IGJ1YmJsZSB0byBzdXJmYWNlIHRoZSBlcnJvci5cbiAgICAgIGF3YWl0IHNlbGVjdGVkUGVyc2lzdGVuY2UuX3NldChrZXksIHVzZXJUb01pZ3JhdGUudG9KU09OKCkpO1xuICAgIH1cblxuICAgIC8vIEF0dGVtcHQgdG8gY2xlYXIgdGhlIGtleSBpbiBvdGhlciBwZXJzaXN0ZW5jZXMgYnV0IGlnbm9yZSBlcnJvcnMuIFRoaXMgaGVscHMgcHJldmVudCBpc3N1ZXNcbiAgICAvLyBzdWNoIGFzIHVzZXJzIGdldHRpbmcgc3R1Y2sgd2l0aCBhIHByZXZpb3VzIGFjY291bnQgYWZ0ZXIgc2lnbmluZyBvdXQgYW5kIHJlZnJlc2hpbmcgdGhlIHRhYi5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5Lm1hcChhc3luYyBwZXJzaXN0ZW5jZSA9PiB7XG4gICAgICAgIGlmIChwZXJzaXN0ZW5jZSAhPT0gc2VsZWN0ZWRQZXJzaXN0ZW5jZSkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBwZXJzaXN0ZW5jZS5fcmVtb3ZlKGtleSk7XG4gICAgICAgICAgfSBjYXRjaCB7fVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIG5ldyBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyKHNlbGVjdGVkUGVyc2lzdGVuY2UsIGF1dGgsIHVzZXJLZXkpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgaXNJRSwgZ2V0VUEgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmludGVyZmFjZSBOYXZpZ2F0b3JTdGFuZGFsb25lIGV4dGVuZHMgTmF2aWdhdG9yIHtcbiAgc3RhbmRhbG9uZT86IHVua25vd247XG59XG5cbmludGVyZmFjZSBEb2N1bWVudCB7XG4gIGRvY3VtZW50TW9kZT86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBFbnVtcyBmb3IgQnJvd3NlciBuYW1lLlxuICovXG5leHBvcnQgY29uc3QgZW51bSBCcm93c2VyTmFtZSB7XG4gIEFORFJPSUQgPSAnQW5kcm9pZCcsXG4gIEJMQUNLQkVSUlkgPSAnQmxhY2tiZXJyeScsXG4gIEVER0UgPSAnRWRnZScsXG4gIEZJUkVGT1ggPSAnRmlyZWZveCcsXG4gIElFID0gJ0lFJyxcbiAgSUVNT0JJTEUgPSAnSUVNb2JpbGUnLFxuICBPUEVSQSA9ICdPcGVyYScsXG4gIE9USEVSID0gJ090aGVyJyxcbiAgQ0hST01FID0gJ0Nocm9tZScsXG4gIFNBRkFSSSA9ICdTYWZhcmknLFxuICBTSUxLID0gJ1NpbGsnLFxuICBXRUJPUyA9ICdXZWJvcydcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgdGhlIGJyb3dzZXIgZm9yIHRoZSBwdXJwb3NlcyBvZiByZXBvcnRpbmcgdXNhZ2UgdG8gdGhlIEFQSVxuICovXG5leHBvcnQgZnVuY3Rpb24gX2dldEJyb3dzZXJOYW1lKHVzZXJBZ2VudDogc3RyaW5nKTogQnJvd3Nlck5hbWUgfCBzdHJpbmcge1xuICBjb25zdCB1YSA9IHVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpO1xuICBpZiAodWEuaW5jbHVkZXMoJ29wZXJhLycpIHx8IHVhLmluY2x1ZGVzKCdvcHIvJykgfHwgdWEuaW5jbHVkZXMoJ29waW9zLycpKSB7XG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLk9QRVJBO1xuICB9IGVsc2UgaWYgKF9pc0lFTW9iaWxlKHVhKSkge1xuICAgIC8vIFdpbmRvd3MgcGhvbmUgSUVNb2JpbGUgYnJvd3Nlci5cbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuSUVNT0JJTEU7XG4gIH0gZWxzZSBpZiAodWEuaW5jbHVkZXMoJ21zaWUnKSB8fCB1YS5pbmNsdWRlcygndHJpZGVudC8nKSkge1xuICAgIHJldHVybiBCcm93c2VyTmFtZS5JRTtcbiAgfSBlbHNlIGlmICh1YS5pbmNsdWRlcygnZWRnZS8nKSkge1xuICAgIHJldHVybiBCcm93c2VyTmFtZS5FREdFO1xuICB9IGVsc2UgaWYgKF9pc0ZpcmVmb3godWEpKSB7XG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLkZJUkVGT1g7XG4gIH0gZWxzZSBpZiAodWEuaW5jbHVkZXMoJ3NpbGsvJykpIHtcbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuU0lMSztcbiAgfSBlbHNlIGlmIChfaXNCbGFja0JlcnJ5KHVhKSkge1xuICAgIC8vIEJsYWNrYmVycnkgYnJvd3Nlci5cbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuQkxBQ0tCRVJSWTtcbiAgfSBlbHNlIGlmIChfaXNXZWJPUyh1YSkpIHtcbiAgICAvLyBXZWJPUyBkZWZhdWx0IGJyb3dzZXIuXG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLldFQk9TO1xuICB9IGVsc2UgaWYgKF9pc1NhZmFyaSh1YSkpIHtcbiAgICByZXR1cm4gQnJvd3Nlck5hbWUuU0FGQVJJO1xuICB9IGVsc2UgaWYgKFxuICAgICh1YS5pbmNsdWRlcygnY2hyb21lLycpIHx8IF9pc0Nocm9tZUlPUyh1YSkpICYmXG4gICAgIXVhLmluY2x1ZGVzKCdlZGdlLycpXG4gICkge1xuICAgIHJldHVybiBCcm93c2VyTmFtZS5DSFJPTUU7XG4gIH0gZWxzZSBpZiAoX2lzQW5kcm9pZCh1YSkpIHtcbiAgICAvLyBBbmRyb2lkIHN0b2NrIGJyb3dzZXIuXG4gICAgcmV0dXJuIEJyb3dzZXJOYW1lLkFORFJPSUQ7XG4gIH0gZWxzZSB7XG4gICAgLy8gTW9zdCBtb2Rlcm4gYnJvd3NlcnMgaGF2ZSBuYW1lL3ZlcnNpb24gYXQgZW5kIG9mIHVzZXIgYWdlbnQgc3RyaW5nLlxuICAgIGNvbnN0IHJlID0gLyhbYS16QS1aXFxkXFwuXSspXFwvW2EtekEtWlxcZFxcLl0qJC87XG4gICAgY29uc3QgbWF0Y2hlcyA9IHVzZXJBZ2VudC5tYXRjaChyZSk7XG4gICAgaWYgKG1hdGNoZXM/Lmxlbmd0aCA9PT0gMikge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbMV07XG4gICAgfVxuICB9XG4gIHJldHVybiBCcm93c2VyTmFtZS5PVEhFUjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0ZpcmVmb3godWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAvZmlyZWZveFxcLy9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzU2FmYXJpKHVzZXJBZ2VudCA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgY29uc3QgdWEgPSB1c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChcbiAgICB1YS5pbmNsdWRlcygnc2FmYXJpLycpICYmXG4gICAgIXVhLmluY2x1ZGVzKCdjaHJvbWUvJykgJiZcbiAgICAhdWEuaW5jbHVkZXMoJ2NyaW9zLycpICYmXG4gICAgIXVhLmluY2x1ZGVzKCdhbmRyb2lkJylcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0Nocm9tZUlPUyh1YSA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9jcmlvc1xcLy9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSUVNb2JpbGUodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAvaWVtb2JpbGUvaS50ZXN0KHVhKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0FuZHJvaWQodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAvYW5kcm9pZC9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzQmxhY2tCZXJyeSh1YSA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9ibGFja2JlcnJ5L2kudGVzdCh1YSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfaXNXZWJPUyh1YSA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgcmV0dXJuIC93ZWJvcy9pLnRlc3QodWEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSU9TKHVhID0gZ2V0VUEoKSk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIC9pcGhvbmV8aXBhZHxpcG9kL2kudGVzdCh1YSkgfHxcbiAgICAoL21hY2ludG9zaC9pLnRlc3QodWEpICYmIC9tb2JpbGUvaS50ZXN0KHVhKSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0lPUzdPcjgodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgLyhpUGFkfGlQaG9uZXxpUG9kKS4qT1MgN19cXGQvaS50ZXN0KHVhKSB8fFxuICAgIC8oaVBhZHxpUGhvbmV8aVBvZCkuKk9TIDhfXFxkL2kudGVzdCh1YSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc0lPU1N0YW5kYWxvbmUodWEgPSBnZXRVQSgpKTogYm9vbGVhbiB7XG4gIHJldHVybiBfaXNJT1ModWEpICYmICEhKHdpbmRvdy5uYXZpZ2F0b3IgYXMgTmF2aWdhdG9yU3RhbmRhbG9uZSk/LnN0YW5kYWxvbmU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfaXNJRTEwKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNJRSgpICYmIChkb2N1bWVudCBhcyBEb2N1bWVudCkuZG9jdW1lbnRNb2RlID09PSAxMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9pc01vYmlsZUJyb3dzZXIodWE6IHN0cmluZyA9IGdldFVBKCkpOiBib29sZWFuIHtcbiAgLy8gVE9ETzogaW1wbGVtZW50IGdldEJyb3dzZXJOYW1lIGVxdWl2YWxlbnQgZm9yIE9TLlxuICByZXR1cm4gKFxuICAgIF9pc0lPUyh1YSkgfHxcbiAgICBfaXNBbmRyb2lkKHVhKSB8fFxuICAgIF9pc1dlYk9TKHVhKSB8fFxuICAgIF9pc0JsYWNrQmVycnkodWEpIHx8XG4gICAgL3dpbmRvd3MgcGhvbmUvaS50ZXN0KHVhKSB8fFxuICAgIF9pc0lFTW9iaWxlKHVhKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2lzSWZyYW1lKCk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIC8vIENoZWNrIHRoYXQgdGhlIGN1cnJlbnQgd2luZG93IGlzIG5vdCB0aGUgdG9wIHdpbmRvdy5cbiAgICAvLyBJZiBzbywgcmV0dXJuIHRydWUuXG4gICAgcmV0dXJuICEhKHdpbmRvdyAmJiB3aW5kb3cgIT09IHdpbmRvdy50b3ApO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgU0RLX1ZFUlNJT04gfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IF9nZXRCcm93c2VyTmFtZSB9IGZyb20gJy4vYnJvd3Nlcic7XG5pbXBvcnQgeyBnZXRVQSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuZXhwb3J0IGNvbnN0IGVudW0gQ2xpZW50SW1wbGVtZW50YXRpb24ge1xuICBDT1JFID0gJ0pzQ29yZSdcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IGVudW0gQ2xpZW50UGxhdGZvcm0ge1xuICBCUk9XU0VSID0gJ0Jyb3dzZXInLFxuICBOT0RFID0gJ05vZGUnLFxuICBSRUFDVF9OQVRJVkUgPSAnUmVhY3ROYXRpdmUnLFxuICBDT1JET1ZBID0gJ0NvcmRvdmEnLFxuICBXT1JLRVIgPSAnV29ya2VyJyxcbiAgV0VCX0VYVEVOU0lPTiA9ICdXZWJFeHRlbnNpb24nXG59XG5cbi8qXG4gKiBEZXRlcm1pbmUgdGhlIFNESyB2ZXJzaW9uIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gX2dldENsaWVudFZlcnNpb24oXG4gIGNsaWVudFBsYXRmb3JtOiBDbGllbnRQbGF0Zm9ybSxcbiAgZnJhbWV3b3JrczogcmVhZG9ubHkgc3RyaW5nW10gPSBbXVxuKTogc3RyaW5nIHtcbiAgbGV0IHJlcG9ydGVkUGxhdGZvcm06IHN0cmluZztcbiAgc3dpdGNoIChjbGllbnRQbGF0Zm9ybSkge1xuICAgIGNhc2UgQ2xpZW50UGxhdGZvcm0uQlJPV1NFUjpcbiAgICAgIC8vIEluIGEgYnJvd3NlciBlbnZpcm9ubWVudCwgcmVwb3J0IHRoZSBicm93c2VyIG5hbWUuXG4gICAgICByZXBvcnRlZFBsYXRmb3JtID0gX2dldEJyb3dzZXJOYW1lKGdldFVBKCkpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBDbGllbnRQbGF0Zm9ybS5XT1JLRVI6XG4gICAgICAvLyBUZWNobmljYWxseSBhIHdvcmtlciBydW5zIGZyb20gYSBicm93c2VyIGJ1dCB3ZSBuZWVkIHRvIGRpZmZlcmVudGlhdGUgYVxuICAgICAgLy8gd29ya2VyIGZyb20gYSBicm93c2VyLlxuICAgICAgLy8gRm9yIGV4YW1wbGU6IENocm9tZS1Xb3JrZXIvSnNDb3JlLzQuOS4xL0ZpcmViYXNlQ29yZS13ZWIuXG4gICAgICByZXBvcnRlZFBsYXRmb3JtID0gYCR7X2dldEJyb3dzZXJOYW1lKGdldFVBKCkpfS0ke2NsaWVudFBsYXRmb3JtfWA7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgcmVwb3J0ZWRQbGF0Zm9ybSA9IGNsaWVudFBsYXRmb3JtO1xuICB9XG4gIGNvbnN0IHJlcG9ydGVkRnJhbWV3b3JrcyA9IGZyYW1ld29ya3MubGVuZ3RoXG4gICAgPyBmcmFtZXdvcmtzLmpvaW4oJywnKVxuICAgIDogJ0ZpcmViYXNlQ29yZS13ZWInOyAvKiBkZWZhdWx0IHZhbHVlIGlmIG5vIG90aGVyIGZyYW1ld29yayBpcyB1c2VkICovXG4gIHJldHVybiBgJHtyZXBvcnRlZFBsYXRmb3JtfS8ke0NsaWVudEltcGxlbWVudGF0aW9uLkNPUkV9LyR7U0RLX1ZFUlNJT059LyR7cmVwb3J0ZWRGcmFtZXdvcmtzfWA7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBVbnN1YnNjcmliZSwgVXNlciB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuaW50ZXJmYWNlIE1pZGRsZXdhcmVFbnRyeSB7XG4gICh1c2VyOiBVc2VyIHwgbnVsbCk6IFByb21pc2U8dm9pZD47XG4gIG9uQWJvcnQ/OiAoKSA9PiB2b2lkO1xufVxuXG5leHBvcnQgY2xhc3MgQXV0aE1pZGRsZXdhcmVRdWV1ZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcXVldWU6IE1pZGRsZXdhcmVFbnRyeVtdID0gW107XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBhdXRoOiBBdXRoSW50ZXJuYWwpIHt9XG5cbiAgcHVzaENhbGxiYWNrKFxuICAgIGNhbGxiYWNrOiAodXNlcjogVXNlciB8IG51bGwpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICAgIG9uQWJvcnQ/OiAoKSA9PiB2b2lkXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICAvLyBUaGUgY2FsbGJhY2sgY291bGQgYmUgc3luYyBvciBhc3luYy4gV3JhcCBpdCBpbnRvIGFcbiAgICAvLyBmdW5jdGlvbiB0aGF0IGlzIGFsd2F5cyBhc3luYy5cbiAgICBjb25zdCB3cmFwcGVkQ2FsbGJhY2s6IE1pZGRsZXdhcmVFbnRyeSA9IChcbiAgICAgIHVzZXI6IFVzZXIgfCBudWxsXG4gICAgKTogUHJvbWlzZTx2b2lkPiA9PlxuICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGNhbGxiYWNrKHVzZXIpO1xuICAgICAgICAgIC8vIEVpdGhlciByZXNvbHZlIHdpdGggZXhpc3RpbmcgcHJvbWlzZSBvciB3cmFwIGEgbm9uLXByb21pc2VcbiAgICAgICAgICAvLyByZXR1cm4gdmFsdWUgaW50byBhIHByb21pc2UuXG4gICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gU3luYyBjYWxsYmFjayB0aHJvd3MuXG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAvLyBBdHRhY2ggdGhlIG9uQWJvcnQgaWYgcHJlc2VudFxuICAgIHdyYXBwZWRDYWxsYmFjay5vbkFib3J0ID0gb25BYm9ydDtcbiAgICB0aGlzLnF1ZXVlLnB1c2god3JhcHBlZENhbGxiYWNrKTtcblxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5xdWV1ZS5sZW5ndGggLSAxO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAvLyBVbnN1YnNjcmliZS4gUmVwbGFjZSB3aXRoIG5vLW9wLiBEbyBub3QgcmVtb3ZlIGZyb20gYXJyYXksIG9yIGl0IHdpbGwgZGlzdHVyYlxuICAgICAgLy8gaW5kZXhpbmcgb2Ygb3RoZXIgZWxlbWVudHMuXG4gICAgICB0aGlzLnF1ZXVlW2luZGV4XSA9ICgpID0+IFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG4gIH1cblxuICBhc3luYyBydW5NaWRkbGV3YXJlKG5leHRVc2VyOiBVc2VyIHwgbnVsbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmF1dGguY3VycmVudFVzZXIgPT09IG5leHRVc2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gV2hpbGUgcnVubmluZyB0aGUgbWlkZGxld2FyZSwgYnVpbGQgYSB0ZW1wb3Jhcnkgc3RhY2sgb2Ygb25BYm9ydFxuICAgIC8vIGNhbGxiYWNrcyB0byBjYWxsIGlmIG9uZSBtaWRkbGV3YXJlIGNhbGxiYWNrIHJlamVjdHMuXG5cbiAgICBjb25zdCBvbkFib3J0U3RhY2s6IEFycmF5PCgpID0+IHZvaWQ+ID0gW107XG4gICAgdHJ5IHtcbiAgICAgIGZvciAoY29uc3QgYmVmb3JlU3RhdGVDYWxsYmFjayBvZiB0aGlzLnF1ZXVlKSB7XG4gICAgICAgIGF3YWl0IGJlZm9yZVN0YXRlQ2FsbGJhY2sobmV4dFVzZXIpO1xuXG4gICAgICAgIC8vIE9ubHkgcHVzaCB0aGUgb25BYm9ydCBpZiB0aGUgY2FsbGJhY2sgc3VjY2VlZHNcbiAgICAgICAgaWYgKGJlZm9yZVN0YXRlQ2FsbGJhY2sub25BYm9ydCkge1xuICAgICAgICAgIG9uQWJvcnRTdGFjay5wdXNoKGJlZm9yZVN0YXRlQ2FsbGJhY2sub25BYm9ydCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBSdW4gYWxsIG9uQWJvcnQsIHdpdGggc2VwYXJhdGUgdHJ5L2NhdGNoIHRvIGlnbm9yZSBhbnkgZXJyb3JzIGFuZFxuICAgICAgLy8gY29udGludWVcbiAgICAgIG9uQWJvcnRTdGFjay5yZXZlcnNlKCk7XG4gICAgICBmb3IgKGNvbnN0IG9uQWJvcnQgb2Ygb25BYm9ydFN0YWNrKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgb25BYm9ydCgpO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgLyogc3dhbGxvdyBlcnJvciAqL1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IHRoaXMuYXV0aC5fZXJyb3JGYWN0b3J5LmNyZWF0ZShBdXRoRXJyb3JDb2RlLkxPR0lOX0JMT0NLRUQsIHtcbiAgICAgICAgb3JpZ2luYWxNZXNzYWdlOiAoZSBhcyBFcnJvcik/Lm1lc3NhZ2VcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeVxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuLyoqXG4gKiBSZXF1ZXN0IG9iamVjdCBmb3IgZmV0Y2hpbmcgdGhlIHBhc3N3b3JkIHBvbGljeS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRQYXNzd29yZFBvbGljeVJlcXVlc3Qge1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXNwb25zZSBvYmplY3QgZm9yIGZldGNoaW5nIHRoZSBwYXNzd29yZCBwb2xpY3kuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UGFzc3dvcmRQb2xpY3lSZXNwb25zZSB7XG4gIGN1c3RvbVN0cmVuZ3RoT3B0aW9uczoge1xuICAgIG1pblBhc3N3b3JkTGVuZ3RoPzogbnVtYmVyO1xuICAgIG1heFBhc3N3b3JkTGVuZ3RoPzogbnVtYmVyO1xuICAgIGNvbnRhaW5zTG93ZXJjYXNlQ2hhcmFjdGVyPzogYm9vbGVhbjtcbiAgICBjb250YWluc1VwcGVyY2FzZUNoYXJhY3Rlcj86IGJvb2xlYW47XG4gICAgY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyPzogYm9vbGVhbjtcbiAgICBjb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3Rlcj86IGJvb2xlYW47XG4gIH07XG4gIGFsbG93ZWROb25BbHBoYW51bWVyaWNDaGFyYWN0ZXJzPzogc3RyaW5nW107XG4gIGVuZm9yY2VtZW50U3RhdGU6IHN0cmluZztcbiAgZm9yY2VVcGdyYWRlT25TaWduaW4/OiBib29sZWFuO1xuICBzY2hlbWFWZXJzaW9uOiBudW1iZXI7XG59XG5cbi8qKlxuICogRmV0Y2hlcyB0aGUgcGFzc3dvcmQgcG9saWN5IGZvciB0aGUgY3VycmVudGx5IHNldCB0ZW5hbnQgb3IgdGhlIHByb2plY3QgaWYgbm8gdGVuYW50IGlzIHNldC5cbiAqXG4gKiBAcGFyYW0gYXV0aCBBdXRoIG9iamVjdC5cbiAqIEBwYXJhbSByZXF1ZXN0IFBhc3N3b3JkIHBvbGljeSByZXF1ZXN0LlxuICogQHJldHVybnMgUGFzc3dvcmQgcG9saWN5IHJlc3BvbnNlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX2dldFBhc3N3b3JkUG9saWN5KFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBHZXRQYXNzd29yZFBvbGljeVJlcXVlc3QgPSB7fVxuKTogUHJvbWlzZTxHZXRQYXNzd29yZFBvbGljeVJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgR2V0UGFzc3dvcmRQb2xpY3lSZXF1ZXN0LFxuICAgIEdldFBhc3N3b3JkUG9saWN5UmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuR0VULFxuICAgIEVuZHBvaW50LkdFVF9QQVNTV09SRF9QT0xJQ1ksXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgR2V0UGFzc3dvcmRQb2xpY3lSZXNwb25zZSB9IGZyb20gJy4uLy4uL2FwaS9wYXNzd29yZF9wb2xpY3kvZ2V0X3Bhc3N3b3JkX3BvbGljeSc7XG5pbXBvcnQge1xuICBQYXNzd29yZFBvbGljeUN1c3RvbVN0cmVuZ3RoT3B0aW9ucyxcbiAgUGFzc3dvcmRQb2xpY3lJbnRlcm5hbCxcbiAgUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWxcbn0gZnJvbSAnLi4vLi4vbW9kZWwvcGFzc3dvcmRfcG9saWN5JztcbmltcG9ydCB7IFBhc3N3b3JkVmFsaWRhdGlvblN0YXR1cyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbi8vIE1pbmltdW0gbWluIHBhc3N3b3JkIGxlbmd0aCBlbmZvcmNlZCBieSB0aGUgYmFja2VuZCwgZXZlbiBpZiBubyBtaW5pbXVtIGxlbmd0aCBpcyBzZXQuXG5jb25zdCBNSU5JTVVNX01JTl9QQVNTV09SRF9MRU5HVEggPSA2O1xuXG4vKipcbiAqIFN0b3JlcyBwYXNzd29yZCBwb2xpY3kgcmVxdWlyZW1lbnRzIGFuZCBwcm92aWRlcyBwYXNzd29yZCB2YWxpZGF0aW9uIGFnYWluc3QgdGhlIHBvbGljeS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNsYXNzIFBhc3N3b3JkUG9saWN5SW1wbCBpbXBsZW1lbnRzIFBhc3N3b3JkUG9saWN5SW50ZXJuYWwge1xuICByZWFkb25seSBjdXN0b21TdHJlbmd0aE9wdGlvbnM6IFBhc3N3b3JkUG9saWN5Q3VzdG9tU3RyZW5ndGhPcHRpb25zO1xuICByZWFkb25seSBhbGxvd2VkTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyczogc3RyaW5nO1xuICByZWFkb25seSBlbmZvcmNlbWVudFN0YXRlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZvcmNlVXBncmFkZU9uU2lnbmluOiBib29sZWFuO1xuICByZWFkb25seSBzY2hlbWFWZXJzaW9uOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IocmVzcG9uc2U6IEdldFBhc3N3b3JkUG9saWN5UmVzcG9uc2UpIHtcbiAgICAvLyBPbmx5IGluY2x1ZGUgY3VzdG9tIHN0cmVuZ3RoIG9wdGlvbnMgZGVmaW5lZCBpbiB0aGUgcmVzcG9uc2UuXG4gICAgY29uc3QgcmVzcG9uc2VPcHRpb25zID0gcmVzcG9uc2UuY3VzdG9tU3RyZW5ndGhPcHRpb25zO1xuICAgIHRoaXMuY3VzdG9tU3RyZW5ndGhPcHRpb25zID0ge307XG4gICAgLy8gVE9ETzogUmVtb3ZlIG9uY2UgdGhlIGJhY2tlbmQgaXMgdXBkYXRlZCB0byBpbmNsdWRlIHRoZSBtaW5pbXVtIG1pbiBwYXNzd29yZCBsZW5ndGggaW5zdGVhZCBvZiB1bmRlZmluZWQgd2hlbiB0aGVyZSBpcyBubyBtaW5pbXVtIGxlbmd0aCBzZXQuXG4gICAgdGhpcy5jdXN0b21TdHJlbmd0aE9wdGlvbnMubWluUGFzc3dvcmRMZW5ndGggPVxuICAgICAgcmVzcG9uc2VPcHRpb25zLm1pblBhc3N3b3JkTGVuZ3RoID8/IE1JTklNVU1fTUlOX1BBU1NXT1JEX0xFTkdUSDtcbiAgICBpZiAocmVzcG9uc2VPcHRpb25zLm1heFBhc3N3b3JkTGVuZ3RoKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5tYXhQYXNzd29yZExlbmd0aCA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5tYXhQYXNzd29yZExlbmd0aDtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUNoYXJhY3RlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUxldHRlciA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUNoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc1VwcGVyY2FzZUNoYXJhY3RlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc1VwcGVyY2FzZUxldHRlciA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5jb250YWluc1VwcGVyY2FzZUNoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc051bWVyaWNDaGFyYWN0ZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5jdXN0b21TdHJlbmd0aE9wdGlvbnMuY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyID1cbiAgICAgICAgcmVzcG9uc2VPcHRpb25zLmNvbnRhaW5zTnVtZXJpY0NoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHJlc3BvbnNlT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlciA9XG4gICAgICAgIHJlc3BvbnNlT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlcjtcbiAgICB9XG5cbiAgICB0aGlzLmVuZm9yY2VtZW50U3RhdGUgPSByZXNwb25zZS5lbmZvcmNlbWVudFN0YXRlO1xuICAgIGlmICh0aGlzLmVuZm9yY2VtZW50U3RhdGUgPT09ICdFTkZPUkNFTUVOVF9TVEFURV9VTlNQRUNJRklFRCcpIHtcbiAgICAgIHRoaXMuZW5mb3JjZW1lbnRTdGF0ZSA9ICdPRkYnO1xuICAgIH1cblxuICAgIC8vIFVzZSBhbiBlbXB0eSBzdHJpbmcgaWYgbm8gbm9uLWFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzIGFyZSBzcGVjaWZpZWQgaW4gdGhlIHJlc3BvbnNlLlxuICAgIHRoaXMuYWxsb3dlZE5vbkFscGhhbnVtZXJpY0NoYXJhY3RlcnMgPVxuICAgICAgcmVzcG9uc2UuYWxsb3dlZE5vbkFscGhhbnVtZXJpY0NoYXJhY3RlcnM/LmpvaW4oJycpID8/ICcnO1xuXG4gICAgdGhpcy5mb3JjZVVwZ3JhZGVPblNpZ25pbiA9IHJlc3BvbnNlLmZvcmNlVXBncmFkZU9uU2lnbmluID8/IGZhbHNlO1xuICAgIHRoaXMuc2NoZW1hVmVyc2lvbiA9IHJlc3BvbnNlLnNjaGVtYVZlcnNpb247XG4gIH1cblxuICB2YWxpZGF0ZVBhc3N3b3JkKHBhc3N3b3JkOiBzdHJpbmcpOiBQYXNzd29yZFZhbGlkYXRpb25TdGF0dXMge1xuICAgIGNvbnN0IHN0YXR1czogUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWwgPSB7XG4gICAgICBpc1ZhbGlkOiB0cnVlLFxuICAgICAgcGFzc3dvcmRQb2xpY3k6IHRoaXNcbiAgICB9O1xuXG4gICAgLy8gQ2hlY2sgdGhlIHBhc3N3b3JkIGxlbmd0aCBhbmQgY2hhcmFjdGVyIG9wdGlvbnMuXG4gICAgdGhpcy52YWxpZGF0ZVBhc3N3b3JkTGVuZ3RoT3B0aW9ucyhwYXNzd29yZCwgc3RhdHVzKTtcbiAgICB0aGlzLnZhbGlkYXRlUGFzc3dvcmRDaGFyYWN0ZXJPcHRpb25zKHBhc3N3b3JkLCBzdGF0dXMpO1xuXG4gICAgLy8gQ29tYmluZSB0aGUgc3RhdHVzIGludG8gc2luZ2xlIGlzVmFsaWQgcHJvcGVydHkuXG4gICAgc3RhdHVzLmlzVmFsaWQgJiY9IHN0YXR1cy5tZWV0c01pblBhc3N3b3JkTGVuZ3RoID8/IHRydWU7XG4gICAgc3RhdHVzLmlzVmFsaWQgJiY9IHN0YXR1cy5tZWV0c01heFBhc3N3b3JkTGVuZ3RoID8/IHRydWU7XG4gICAgc3RhdHVzLmlzVmFsaWQgJiY9IHN0YXR1cy5jb250YWluc0xvd2VyY2FzZUxldHRlciA/PyB0cnVlO1xuICAgIHN0YXR1cy5pc1ZhbGlkICYmPSBzdGF0dXMuY29udGFpbnNVcHBlcmNhc2VMZXR0ZXIgPz8gdHJ1ZTtcbiAgICBzdGF0dXMuaXNWYWxpZCAmJj0gc3RhdHVzLmNvbnRhaW5zTnVtZXJpY0NoYXJhY3RlciA/PyB0cnVlO1xuICAgIHN0YXR1cy5pc1ZhbGlkICYmPSBzdGF0dXMuY29udGFpbnNOb25BbHBoYW51bWVyaWNDaGFyYWN0ZXIgPz8gdHJ1ZTtcblxuICAgIHJldHVybiBzdGF0dXM7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoYXQgdGhlIHBhc3N3b3JkIG1lZXRzIHRoZSBsZW5ndGggb3B0aW9ucyBmb3IgdGhlIHBvbGljeS5cbiAgICpcbiAgICogQHBhcmFtIHBhc3N3b3JkIFBhc3N3b3JkIHRvIHZhbGlkYXRlLlxuICAgKiBAcGFyYW0gc3RhdHVzIFZhbGlkYXRpb24gc3RhdHVzLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVBhc3N3b3JkTGVuZ3RoT3B0aW9ucyhcbiAgICBwYXNzd29yZDogc3RyaW5nLFxuICAgIHN0YXR1czogUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgbWluUGFzc3dvcmRMZW5ndGggPSB0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5taW5QYXNzd29yZExlbmd0aDtcbiAgICBjb25zdCBtYXhQYXNzd29yZExlbmd0aCA9IHRoaXMuY3VzdG9tU3RyZW5ndGhPcHRpb25zLm1heFBhc3N3b3JkTGVuZ3RoO1xuICAgIGlmIChtaW5QYXNzd29yZExlbmd0aCkge1xuICAgICAgc3RhdHVzLm1lZXRzTWluUGFzc3dvcmRMZW5ndGggPSBwYXNzd29yZC5sZW5ndGggPj0gbWluUGFzc3dvcmRMZW5ndGg7XG4gICAgfVxuICAgIGlmIChtYXhQYXNzd29yZExlbmd0aCkge1xuICAgICAgc3RhdHVzLm1lZXRzTWF4UGFzc3dvcmRMZW5ndGggPSBwYXNzd29yZC5sZW5ndGggPD0gbWF4UGFzc3dvcmRMZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGF0IHRoZSBwYXNzd29yZCBtZWV0cyB0aGUgY2hhcmFjdGVyIG9wdGlvbnMgZm9yIHRoZSBwb2xpY3kuXG4gICAqXG4gICAqIEBwYXJhbSBwYXNzd29yZCBQYXNzd29yZCB0byB2YWxpZGF0ZS5cbiAgICogQHBhcmFtIHN0YXR1cyBWYWxpZGF0aW9uIHN0YXR1cy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVQYXNzd29yZENoYXJhY3Rlck9wdGlvbnMoXG4gICAgcGFzc3dvcmQ6IHN0cmluZyxcbiAgICBzdGF0dXM6IFBhc3N3b3JkVmFsaWRhdGlvblN0YXR1c0ludGVybmFsXG4gICk6IHZvaWQge1xuICAgIC8vIEFzc2lnbiBzdGF0dXNlcyBmb3IgcmVxdWlyZW1lbnRzIGV2ZW4gaWYgdGhlIHBhc3N3b3JkIGlzIGFuIGVtcHR5IHN0cmluZy5cbiAgICB0aGlzLnVwZGF0ZVBhc3N3b3JkQ2hhcmFjdGVyT3B0aW9uc1N0YXR1c2VzKFxuICAgICAgc3RhdHVzLFxuICAgICAgLyogY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXI9ICovIGZhbHNlLFxuICAgICAgLyogY29udGFpbnNVcHBlcmNhc2VDaGFyYWN0ZXI9ICovIGZhbHNlLFxuICAgICAgLyogY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyPSAqLyBmYWxzZSxcbiAgICAgIC8qIGNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyPSAqLyBmYWxzZVxuICAgICk7XG5cbiAgICBsZXQgcGFzc3dvcmRDaGFyO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFzc3dvcmQubGVuZ3RoOyBpKyspIHtcbiAgICAgIHBhc3N3b3JkQ2hhciA9IHBhc3N3b3JkLmNoYXJBdChpKTtcbiAgICAgIHRoaXMudXBkYXRlUGFzc3dvcmRDaGFyYWN0ZXJPcHRpb25zU3RhdHVzZXMoXG4gICAgICAgIHN0YXR1cyxcbiAgICAgICAgLyogY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXI9ICovIHBhc3N3b3JkQ2hhciA+PSAnYScgJiZcbiAgICAgICAgICBwYXNzd29yZENoYXIgPD0gJ3onLFxuICAgICAgICAvKiBjb250YWluc1VwcGVyY2FzZUNoYXJhY3Rlcj0gKi8gcGFzc3dvcmRDaGFyID49ICdBJyAmJlxuICAgICAgICAgIHBhc3N3b3JkQ2hhciA8PSAnWicsXG4gICAgICAgIC8qIGNvbnRhaW5zTnVtZXJpY0NoYXJhY3Rlcj0gKi8gcGFzc3dvcmRDaGFyID49ICcwJyAmJlxuICAgICAgICAgIHBhc3N3b3JkQ2hhciA8PSAnOScsXG4gICAgICAgIC8qIGNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyPSAqLyB0aGlzLmFsbG93ZWROb25BbHBoYW51bWVyaWNDaGFyYWN0ZXJzLmluY2x1ZGVzKFxuICAgICAgICAgIHBhc3N3b3JkQ2hhclxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBydW5uaW5nIHZhbGlkYXRpb24gc3RhdHVzIHdpdGggdGhlIHN0YXR1c2VzIGZvciB0aGUgY2hhcmFjdGVyIG9wdGlvbnMuXG4gICAqIEV4cGVjdGVkIHRvIGJlIGNhbGxlZCBlYWNoIHRpbWUgYSBjaGFyYWN0ZXIgaXMgcHJvY2Vzc2VkIHRvIHVwZGF0ZSBlYWNoIG9wdGlvbiBzdGF0dXNcbiAgICogYmFzZWQgb24gdGhlIGN1cnJlbnQgY2hhcmFjdGVyLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdHVzIFZhbGlkYXRpb24gc3RhdHVzLlxuICAgKiBAcGFyYW0gY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXIgV2hldGhlciB0aGUgY2hhcmFjdGVyIGlzIGEgbG93ZXJjYXNlIGxldHRlci5cbiAgICogQHBhcmFtIGNvbnRhaW5zVXBwZXJjYXNlQ2hhcmFjdGVyIFdoZXRoZXIgdGhlIGNoYXJhY3RlciBpcyBhbiB1cHBlcmNhc2UgbGV0dGVyLlxuICAgKiBAcGFyYW0gY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyIFdoZXRoZXIgdGhlIGNoYXJhY3RlciBpcyBhIG51bWVyaWMgY2hhcmFjdGVyLlxuICAgKiBAcGFyYW0gY29udGFpbnNOb25BbHBoYW51bWVyaWNDaGFyYWN0ZXIgV2hldGhlciB0aGUgY2hhcmFjdGVyIGlzIGEgbm9uLWFscGhhbnVtZXJpYyBjaGFyYWN0ZXIuXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZVBhc3N3b3JkQ2hhcmFjdGVyT3B0aW9uc1N0YXR1c2VzKFxuICAgIHN0YXR1czogUGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzSW50ZXJuYWwsXG4gICAgY29udGFpbnNMb3dlcmNhc2VDaGFyYWN0ZXI6IGJvb2xlYW4sXG4gICAgY29udGFpbnNVcHBlcmNhc2VDaGFyYWN0ZXI6IGJvb2xlYW4sXG4gICAgY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyOiBib29sZWFuLFxuICAgIGNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyOiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIGlmICh0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc0xvd2VyY2FzZUxldHRlcikge1xuICAgICAgc3RhdHVzLmNvbnRhaW5zTG93ZXJjYXNlTGV0dGVyIHx8PSBjb250YWluc0xvd2VyY2FzZUNoYXJhY3RlcjtcbiAgICB9XG4gICAgaWYgKHRoaXMuY3VzdG9tU3RyZW5ndGhPcHRpb25zLmNvbnRhaW5zVXBwZXJjYXNlTGV0dGVyKSB7XG4gICAgICBzdGF0dXMuY29udGFpbnNVcHBlcmNhc2VMZXR0ZXIgfHw9IGNvbnRhaW5zVXBwZXJjYXNlQ2hhcmFjdGVyO1xuICAgIH1cbiAgICBpZiAodGhpcy5jdXN0b21TdHJlbmd0aE9wdGlvbnMuY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyKSB7XG4gICAgICBzdGF0dXMuY29udGFpbnNOdW1lcmljQ2hhcmFjdGVyIHx8PSBjb250YWluc051bWVyaWNDaGFyYWN0ZXI7XG4gICAgfVxuICAgIGlmICh0aGlzLmN1c3RvbVN0cmVuZ3RoT3B0aW9ucy5jb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3Rlcikge1xuICAgICAgc3RhdHVzLmNvbnRhaW5zTm9uQWxwaGFudW1lcmljQ2hhcmFjdGVyIHx8PVxuICAgICAgICBjb250YWluc05vbkFscGhhbnVtZXJpY0NoYXJhY3RlcjtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBfaXNGaXJlYmFzZVNlcnZlckFwcCxcbiAgX0ZpcmViYXNlU2VydmljZSxcbiAgRmlyZWJhc2VBcHBcbn0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBQcm92aWRlciB9IGZyb20gJ0BmaXJlYmFzZS9jb21wb25lbnQnO1xuaW1wb3J0IHsgQXBwQ2hlY2tJbnRlcm5hbENvbXBvbmVudE5hbWUgfSBmcm9tICdAZmlyZWJhc2UvYXBwLWNoZWNrLWludGVyb3AtdHlwZXMnO1xuaW1wb3J0IHtcbiAgQXV0aCxcbiAgQXV0aEVycm9yTWFwLFxuICBBdXRoU2V0dGluZ3MsXG4gIEVtdWxhdG9yQ29uZmlnLFxuICBOZXh0T3JPYnNlcnZlcixcbiAgUGVyc2lzdGVuY2UsXG4gIFBvcHVwUmVkaXJlY3RSZXNvbHZlcixcbiAgVXNlcixcbiAgVXNlckNyZWRlbnRpYWwsXG4gIENvbXBsZXRlRm4sXG4gIEVycm9yRm4sXG4gIE5leHRGbixcbiAgVW5zdWJzY3JpYmUsXG4gIFBhc3N3b3JkVmFsaWRhdGlvblN0YXR1c1xufSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlU3Vic2NyaWJlLFxuICBFcnJvckZhY3RvcnksXG4gIEZpcmViYXNlRXJyb3IsXG4gIGdldE1vZHVsYXJJbnN0YW5jZSxcbiAgT2JzZXJ2ZXIsXG4gIFN1YnNjcmliZVxufSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7IEF1dGhJbnRlcm5hbCwgQ29uZmlnSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7IFBvcHVwUmVkaXJlY3RSZXNvbHZlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcG9wdXBfcmVkaXJlY3QnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQge1xuICBBdXRoRXJyb3JDb2RlLFxuICBBdXRoRXJyb3JQYXJhbXMsXG4gIEVycm9yTWFwUmV0cmlldmVyLFxuICBfREVGQVVMVF9BVVRIX0VSUk9SX0ZBQ1RPUllcbn0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IFBlcnNpc3RlbmNlSW50ZXJuYWwgfSBmcm9tICcuLi9wZXJzaXN0ZW5jZSc7XG5pbXBvcnQge1xuICBLZXlOYW1lLFxuICBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyXG59IGZyb20gJy4uL3BlcnNpc3RlbmNlL3BlcnNpc3RlbmNlX3VzZXJfbWFuYWdlcic7XG5pbXBvcnQgeyBfcmVsb2FkV2l0aG91dFNhdmluZyB9IGZyb20gJy4uL3VzZXIvcmVsb2FkJztcbmltcG9ydCB7XG4gIF9hc3NlcnQsXG4gIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yXG59IGZyb20gJy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7IF9nZXRJbnN0YW5jZSB9IGZyb20gJy4uL3V0aWwvaW5zdGFudGlhdG9yJztcbmltcG9ydCB7IF9nZXRVc2VyTGFuZ3VhZ2UgfSBmcm9tICcuLi91dGlsL25hdmlnYXRvcic7XG5pbXBvcnQgeyBfZ2V0Q2xpZW50VmVyc2lvbiB9IGZyb20gJy4uL3V0aWwvdmVyc2lvbic7XG5pbXBvcnQgeyBIdHRwSGVhZGVyIH0gZnJvbSAnLi4vLi4vYXBpJztcbmltcG9ydCB7XG4gIFJldm9rZVRva2VuUmVxdWVzdCxcbiAgVG9rZW5UeXBlLFxuICByZXZva2VUb2tlblxufSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vdG9rZW4nO1xuaW1wb3J0IHsgQXV0aE1pZGRsZXdhcmVRdWV1ZSB9IGZyb20gJy4vbWlkZGxld2FyZSc7XG5pbXBvcnQgeyBSZWNhcHRjaGFDb25maWcgfSBmcm9tICcuLi8uLi9wbGF0Zm9ybV9icm93c2VyL3JlY2FwdGNoYS9yZWNhcHRjaGEnO1xuaW1wb3J0IHsgX2xvZ1dhcm4gfSBmcm9tICcuLi91dGlsL2xvZyc7XG5pbXBvcnQgeyBfZ2V0UGFzc3dvcmRQb2xpY3kgfSBmcm9tICcuLi8uLi9hcGkvcGFzc3dvcmRfcG9saWN5L2dldF9wYXNzd29yZF9wb2xpY3knO1xuaW1wb3J0IHsgUGFzc3dvcmRQb2xpY3lJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3Bhc3N3b3JkX3BvbGljeSc7XG5pbXBvcnQgeyBQYXNzd29yZFBvbGljeUltcGwgfSBmcm9tICcuL3Bhc3N3b3JkX3BvbGljeV9pbXBsJztcbmltcG9ydCB7IGdldEFjY291bnRJbmZvIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IFVzZXJJbXBsIH0gZnJvbSAnLi4vdXNlci91c2VyX2ltcGwnO1xuXG5pbnRlcmZhY2UgQXN5bmNBY3Rpb24ge1xuICAoKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuZXhwb3J0IGNvbnN0IGVudW0gRGVmYXVsdENvbmZpZyB7XG4gIFRPS0VOX0FQSV9IT1NUID0gJ3NlY3VyZXRva2VuLmdvb2dsZWFwaXMuY29tJyxcbiAgQVBJX0hPU1QgPSAnaWRlbnRpdHl0b29sa2l0Lmdvb2dsZWFwaXMuY29tJyxcbiAgQVBJX1NDSEVNRSA9ICdodHRwcydcbn1cblxuZXhwb3J0IGNsYXNzIEF1dGhJbXBsIGltcGxlbWVudHMgQXV0aEludGVybmFsLCBfRmlyZWJhc2VTZXJ2aWNlIHtcbiAgY3VycmVudFVzZXI6IFVzZXIgfCBudWxsID0gbnVsbDtcbiAgZW11bGF0b3JDb25maWc6IEVtdWxhdG9yQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgb3BlcmF0aW9ucyA9IFByb21pc2UucmVzb2x2ZSgpO1xuICBwcml2YXRlIHBlcnNpc3RlbmNlTWFuYWdlcj86IFBlcnNpc3RlbmNlVXNlck1hbmFnZXI7XG4gIHByaXZhdGUgcmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXI/OiBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyO1xuICBwcml2YXRlIGF1dGhTdGF0ZVN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb248VXNlcj4odGhpcyk7XG4gIHByaXZhdGUgaWRUb2tlblN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb248VXNlcj4odGhpcyk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmVmb3JlU3RhdGVRdWV1ZSA9IG5ldyBBdXRoTWlkZGxld2FyZVF1ZXVlKHRoaXMpO1xuICBwcml2YXRlIHJlZGlyZWN0VXNlcjogVXNlckludGVybmFsIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaXNQcm9hY3RpdmVSZWZyZXNoRW5hYmxlZCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWRvbmx5IEVYUEVDVEVEX1BBU1NXT1JEX1BPTElDWV9TQ0hFTUFfVkVSU0lPTjogbnVtYmVyID0gMTtcblxuICAvLyBBbnkgbmV0d29yayBjYWxscyB3aWxsIHNldCB0aGlzIHRvIHRydWUgYW5kIHByZXZlbnQgc3Vic2VxdWVudCBlbXVsYXRvclxuICAvLyBpbml0aWFsaXphdGlvblxuICBfY2FuSW5pdEVtdWxhdG9yID0gdHJ1ZTtcbiAgX2lzSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgX2RlbGV0ZWQgPSBmYWxzZTtcbiAgX2luaXRpYWxpemF0aW9uUHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuICBfcG9wdXBSZWRpcmVjdFJlc29sdmVyOiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJJbnRlcm5hbCB8IG51bGwgPSBudWxsO1xuICBfZXJyb3JGYWN0b3J5OiBFcnJvckZhY3Rvcnk8QXV0aEVycm9yQ29kZSwgQXV0aEVycm9yUGFyYW1zPiA9XG4gICAgX0RFRkFVTFRfQVVUSF9FUlJPUl9GQUNUT1JZO1xuICBfYWdlbnRSZWNhcHRjaGFDb25maWc6IFJlY2FwdGNoYUNvbmZpZyB8IG51bGwgPSBudWxsO1xuICBfdGVuYW50UmVjYXB0Y2hhQ29uZmlnczogUmVjb3JkPHN0cmluZywgUmVjYXB0Y2hhQ29uZmlnPiA9IHt9O1xuICBfcHJvamVjdFBhc3N3b3JkUG9saWN5OiBQYXNzd29yZFBvbGljeUludGVybmFsIHwgbnVsbCA9IG51bGw7XG4gIF90ZW5hbnRQYXNzd29yZFBvbGljaWVzOiBSZWNvcmQ8c3RyaW5nLCBQYXNzd29yZFBvbGljeUludGVybmFsPiA9IHt9O1xuICBfcmVzb2x2ZVBlcnNpc3RlbmNlTWFuYWdlckF2YWlsYWJsZTpcbiAgICB8ICgodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZClcbiAgICB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgX3BlcnNpc3RlbmNlTWFuYWdlckF2YWlsYWJsZTogUHJvbWlzZTx2b2lkPjtcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8vIFRyYWNrcyB0aGUgbGFzdCBub3RpZmllZCBVSUQgZm9yIHN0YXRlIGNoYW5nZSBsaXN0ZW5lcnMgdG8gcHJldmVudFxuICAvLyByZXBlYXRlZCBjYWxscyB0byB0aGUgY2FsbGJhY2tzLiBVbmRlZmluZWQgbWVhbnMgaXQncyBuZXZlciBiZWVuXG4gIC8vIGNhbGxlZCwgd2hlcmVhcyBudWxsIG1lYW5zIGl0J3MgYmVlbiBjYWxsZWQgd2l0aCBhIHNpZ25lZCBvdXQgdXNlclxuICBwcml2YXRlIGxhc3ROb3RpZmllZFVpZDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBsYW5ndWFnZUNvZGU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICB0ZW5hbnRJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHNldHRpbmdzOiBBdXRoU2V0dGluZ3MgPSB7IGFwcFZlcmlmaWNhdGlvbkRpc2FibGVkRm9yVGVzdGluZzogZmFsc2UgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgYXBwOiBGaXJlYmFzZUFwcCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhlYXJ0YmVhdFNlcnZpY2VQcm92aWRlcjogUHJvdmlkZXI8J2hlYXJ0YmVhdCc+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXBwQ2hlY2tTZXJ2aWNlUHJvdmlkZXI6IFByb3ZpZGVyPEFwcENoZWNrSW50ZXJuYWxDb21wb25lbnROYW1lPixcbiAgICBwdWJsaWMgcmVhZG9ubHkgY29uZmlnOiBDb25maWdJbnRlcm5hbFxuICApIHtcbiAgICB0aGlzLm5hbWUgPSBhcHAubmFtZTtcbiAgICB0aGlzLmNsaWVudFZlcnNpb24gPSBjb25maWcuc2RrQ2xpZW50VmVyc2lvbjtcbiAgICAvLyBUT0RPKGphbWVzZGFuaWVscykgZXhwbG9yZSBsZXNzIGhhY2t5IHdheSB0byBkbyB0aGlzLCBjb29raWUgYXV0aGVudGljYXRpb24gbmVlZHNcbiAgICAvLyBwZXJzaXN0ZW5jZU1hbmFuZ2VyIHRvIGJlIGF2YWlsYWJsZS4gc2VlIF9nZXRGaW5hbFRhcmdldCBmb3IgbW9yZSBjb250ZXh0XG4gICAgdGhpcy5fcGVyc2lzdGVuY2VNYW5hZ2VyQXZhaWxhYmxlID0gbmV3IFByb21pc2U8dm9pZD4oXG4gICAgICByZXNvbHZlID0+ICh0aGlzLl9yZXNvbHZlUGVyc2lzdGVuY2VNYW5hZ2VyQXZhaWxhYmxlID0gcmVzb2x2ZSlcbiAgICApO1xuICB9XG5cbiAgX2luaXRpYWxpemVXaXRoUGVyc2lzdGVuY2UoXG4gICAgcGVyc2lzdGVuY2VIaWVyYXJjaHk6IFBlcnNpc3RlbmNlSW50ZXJuYWxbXSxcbiAgICBwb3B1cFJlZGlyZWN0UmVzb2x2ZXI/OiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHBvcHVwUmVkaXJlY3RSZXNvbHZlcikge1xuICAgICAgdGhpcy5fcG9wdXBSZWRpcmVjdFJlc29sdmVyID0gX2dldEluc3RhbmNlKHBvcHVwUmVkaXJlY3RSZXNvbHZlcik7XG4gICAgfVxuXG4gICAgLy8gSGF2ZSB0byBjaGVjayBmb3IgYXBwIGRlbGV0aW9uIHRocm91Z2hvdXQgaW5pdGlhbGl6YXRpb24gKGFmdGVyIGVhY2hcbiAgICAvLyBwcm9taXNlIHJlc29sdXRpb24pXG4gICAgdGhpcy5faW5pdGlhbGl6YXRpb25Qcm9taXNlID0gdGhpcy5xdWV1ZShhc3luYyAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fZGVsZXRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMucGVyc2lzdGVuY2VNYW5hZ2VyID0gYXdhaXQgUGVyc2lzdGVuY2VVc2VyTWFuYWdlci5jcmVhdGUoXG4gICAgICAgIHRoaXMsXG4gICAgICAgIHBlcnNpc3RlbmNlSGllcmFyY2h5XG4gICAgICApO1xuICAgICAgdGhpcy5fcmVzb2x2ZVBlcnNpc3RlbmNlTWFuYWdlckF2YWlsYWJsZT8uKCk7XG5cbiAgICAgIGlmICh0aGlzLl9kZWxldGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgcmVzb2x2ZXIgZWFybHkgaWYgbmVjZXNzYXJ5IChvbmx5IGFwcGxpY2FibGUgdG8gd2ViOlxuICAgICAgLy8gdGhpcyB3aWxsIGNhdXNlIHRoZSBpZnJhbWUgdG8gbG9hZCBpbW1lZGlhdGVseSBpbiBjZXJ0YWluIGNhc2VzKVxuICAgICAgaWYgKHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlcj8uX3Nob3VsZEluaXRQcm9hY3RpdmVseSkge1xuICAgICAgICAvLyBJZiB0aGlzIGZhaWxzLCBkb24ndCBoYWx0IGF1dGggbG9hZGluZ1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlci5faW5pdGlhbGl6ZSh0aGlzKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIC8qIElnbm9yZSB0aGUgZXJyb3IgKi9cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLmluaXRpYWxpemVDdXJyZW50VXNlcihwb3B1cFJlZGlyZWN0UmVzb2x2ZXIpO1xuXG4gICAgICB0aGlzLmxhc3ROb3RpZmllZFVpZCA9IHRoaXMuY3VycmVudFVzZXI/LnVpZCB8fCBudWxsO1xuXG4gICAgICBpZiAodGhpcy5fZGVsZXRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2luaXRpYWxpemF0aW9uUHJvbWlzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGUgcGVyc2lzdGVuY2UgaXMgY2hhbmdlZCBpbiBhbm90aGVyIHdpbmRvdywgdGhlIHVzZXIgbWFuYWdlciB3aWxsIGxldCB1cyBrbm93XG4gICAqL1xuICBhc3luYyBfb25TdG9yYWdlRXZlbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuX2RlbGV0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5hc3NlcnRlZFBlcnNpc3RlbmNlLmdldEN1cnJlbnRVc2VyKCk7XG5cbiAgICBpZiAoIXRoaXMuY3VycmVudFVzZXIgJiYgIXVzZXIpIHtcbiAgICAgIC8vIE5vIGNoYW5nZSwgZG8gbm90aGluZyAod2FzIHNpZ25lZCBvdXQgYW5kIHJlbWFpbmVkIHNpZ25lZCBvdXQpLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBzYW1lIHVzZXIgaXMgdG8gYmUgc3luY2hyb25pemVkLlxuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyICYmIHVzZXIgJiYgdGhpcy5jdXJyZW50VXNlci51aWQgPT09IHVzZXIudWlkKSB7XG4gICAgICAvLyBEYXRhIHVwZGF0ZSwgc2ltcGx5IGNvcHkgZGF0YSBjaGFuZ2VzLlxuICAgICAgdGhpcy5fY3VycmVudFVzZXIuX2Fzc2lnbih1c2VyKTtcbiAgICAgIC8vIElmIHRva2VucyBjaGFuZ2VkIGZyb20gcHJldmlvdXMgdXNlciB0b2tlbnMsIHRoaXMgd2lsbCB0cmlnZ2VyXG4gICAgICAvLyBub3RpZnlBdXRoTGlzdGVuZXJzXy5cbiAgICAgIGF3YWl0IHRoaXMuY3VycmVudFVzZXIuZ2V0SWRUb2tlbigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBjdXJyZW50IEF1dGggc3RhdGUuIEVpdGhlciBhIG5ldyBsb2dpbiBvciBsb2dvdXQuXG4gICAgLy8gU2tpcCBibG9ja2luZyBjYWxsYmFja3MsIHRoZXkgc2hvdWxkIG5vdCBhcHBseSB0byBhIGNoYW5nZSBpbiBhbm90aGVyIHRhYi5cbiAgICBhd2FpdCB0aGlzLl91cGRhdGVDdXJyZW50VXNlcih1c2VyLCAvKiBza2lwQmVmb3JlU3RhdGVDYWxsYmFja3MgKi8gdHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVDdXJyZW50VXNlckZyb21JZFRva2VuKFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBnZXRBY2NvdW50SW5mbyh0aGlzLCB7IGlkVG9rZW4gfSk7XG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgVXNlckltcGwuX2Zyb21HZXRBY2NvdW50SW5mb1Jlc3BvbnNlKFxuICAgICAgICB0aGlzLFxuICAgICAgICByZXNwb25zZSxcbiAgICAgICAgaWRUb2tlblxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuZGlyZWN0bHlTZXRDdXJyZW50VXNlcih1c2VyKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ0ZpcmViYXNlU2VydmVyQXBwIGNvdWxkIG5vdCBsb2dpbiB1c2VyIHdpdGggcHJvdmlkZWQgYXV0aElkVG9rZW46ICcsXG4gICAgICAgIGVyclxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuZGlyZWN0bHlTZXRDdXJyZW50VXNlcihudWxsKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVDdXJyZW50VXNlcihcbiAgICBwb3B1cFJlZGlyZWN0UmVzb2x2ZXI/OiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKHRoaXMuYXBwKSkge1xuICAgICAgY29uc3QgaWRUb2tlbiA9IHRoaXMuYXBwLnNldHRpbmdzLmF1dGhJZFRva2VuO1xuICAgICAgaWYgKGlkVG9rZW4pIHtcbiAgICAgICAgLy8gU3RhcnQgdGhlIGF1dGggb3BlcmF0aW9uIGluIHRoZSBuZXh0IHRpY2sgdG8gYWxsb3cgYSBtb21lbnQgZm9yIHRoZSBjdXN0b21lcidzIGFwcCB0b1xuICAgICAgICAvLyBhdHRhY2ggYW4gZW11bGF0b3IsIGlmIGRlc2lyZWQuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPihyZXNvbHZlID0+IHtcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVDdXJyZW50VXNlckZyb21JZFRva2VuKGlkVG9rZW4pLnRoZW4oXG4gICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICAgIHJlc29sdmVcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIobnVsbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmlyc3QgY2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYSBwZW5kaW5nIHJlZGlyZWN0IGV2ZW50LlxuICAgIGNvbnN0IHByZXZpb3VzbHlTdG9yZWRVc2VyID1cbiAgICAgIChhd2FpdCB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2UuZ2V0Q3VycmVudFVzZXIoKSkgYXMgVXNlckludGVybmFsIHwgbnVsbDtcbiAgICBsZXQgZnV0dXJlQ3VycmVudFVzZXIgPSBwcmV2aW91c2x5U3RvcmVkVXNlcjtcbiAgICBsZXQgbmVlZHNUb2NoZWNrTWlkZGxld2FyZSA9IGZhbHNlO1xuICAgIGlmIChwb3B1cFJlZGlyZWN0UmVzb2x2ZXIgJiYgdGhpcy5jb25maWcuYXV0aERvbWFpbikge1xuICAgICAgYXdhaXQgdGhpcy5nZXRPckluaXRSZWRpcmVjdFBlcnNpc3RlbmNlTWFuYWdlcigpO1xuICAgICAgY29uc3QgcmVkaXJlY3RVc2VyRXZlbnRJZCA9IHRoaXMucmVkaXJlY3RVc2VyPy5fcmVkaXJlY3RFdmVudElkO1xuICAgICAgY29uc3Qgc3RvcmVkVXNlckV2ZW50SWQgPSBmdXR1cmVDdXJyZW50VXNlcj8uX3JlZGlyZWN0RXZlbnRJZDtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudHJ5UmVkaXJlY3RTaWduSW4ocG9wdXBSZWRpcmVjdFJlc29sdmVyKTtcblxuICAgICAgLy8gSWYgdGhlIHN0b3JlZCB1c2VyIChpLmUuIHRoZSBvbGQgXCJjdXJyZW50VXNlclwiKSBoYXMgYSByZWRpcmVjdElkIHRoYXRcbiAgICAgIC8vIG1hdGNoZXMgdGhlIHJlZGlyZWN0IHVzZXIsIHRoZW4gd2Ugd2FudCB0byBpbml0aWFsbHkgc2lnbiBpbiB3aXRoIHRoZVxuICAgICAgLy8gbmV3IHVzZXIgb2JqZWN0IGZyb20gcmVzdWx0LlxuICAgICAgLy8gVE9ETyhzYW1naG8pOiBNb3JlIHRob3JvdWdobHkgdGVzdCBhbGwgb2YgdGhpc1xuICAgICAgaWYgKFxuICAgICAgICAoIXJlZGlyZWN0VXNlckV2ZW50SWQgfHwgcmVkaXJlY3RVc2VyRXZlbnRJZCA9PT0gc3RvcmVkVXNlckV2ZW50SWQpICYmXG4gICAgICAgIHJlc3VsdD8udXNlclxuICAgICAgKSB7XG4gICAgICAgIGZ1dHVyZUN1cnJlbnRVc2VyID0gcmVzdWx0LnVzZXIgYXMgVXNlckludGVybmFsO1xuICAgICAgICBuZWVkc1RvY2hlY2tNaWRkbGV3YXJlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiBubyB1c2VyIGluIHBlcnNpc3RlbmNlLCB0aGVyZSBpcyBubyBjdXJyZW50IHVzZXIuIFNldCB0byBudWxsLlxuICAgIGlmICghZnV0dXJlQ3VycmVudFVzZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIobnVsbCk7XG4gICAgfVxuXG4gICAgaWYgKCFmdXR1cmVDdXJyZW50VXNlci5fcmVkaXJlY3RFdmVudElkKSB7XG4gICAgICAvLyBUaGlzIGlzbid0IGEgcmVkaXJlY3QgbGluayBvcGVyYXRpb24sIHdlIGNhbiByZWxvYWQgYW5kIGJhaWwuXG4gICAgICAvLyBGaXJzdCB0aG91Z2gsIGVuc3VyZSB0aGF0IHdlIGNoZWNrIHRoZSBtaWRkbGV3YXJlIGlzIGhhcHB5LlxuICAgICAgaWYgKG5lZWRzVG9jaGVja01pZGRsZXdhcmUpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmJlZm9yZVN0YXRlUXVldWUucnVuTWlkZGxld2FyZShmdXR1cmVDdXJyZW50VXNlcik7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBmdXR1cmVDdXJyZW50VXNlciA9IHByZXZpb3VzbHlTdG9yZWRVc2VyO1xuICAgICAgICAgIC8vIFdlIGtub3cgdGhpcyBpcyBhdmFpbGFibGUgc2luY2UgdGhlIGJpdCBpcyBvbmx5IHNldCB3aGVuIHRoZVxuICAgICAgICAgIC8vIHJlc29sdmVyIGlzIGF2YWlsYWJsZVxuICAgICAgICAgIHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlciEuX292ZXJyaWRlUmVkaXJlY3RSZXN1bHQodGhpcywgKCkgPT5cbiAgICAgICAgICAgIFByb21pc2UucmVqZWN0KGUpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZnV0dXJlQ3VycmVudFVzZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVsb2FkQW5kU2V0Q3VycmVudFVzZXJPckNsZWFyKGZ1dHVyZUN1cnJlbnRVc2VyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIobnVsbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2Fzc2VydCh0aGlzLl9wb3B1cFJlZGlyZWN0UmVzb2x2ZXIsIHRoaXMsIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1IpO1xuICAgIGF3YWl0IHRoaXMuZ2V0T3JJbml0UmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIoKTtcblxuICAgIC8vIElmIHRoZSByZWRpcmVjdCB1c2VyJ3MgZXZlbnQgSUQgbWF0Y2hlcyB0aGUgY3VycmVudCB1c2VyJ3MgZXZlbnQgSUQsXG4gICAgLy8gRE8gTk9UIHJlbG9hZCB0aGUgY3VycmVudCB1c2VyLCBvdGhlcndpc2UgdGhleSdsbCBiZSBjbGVhcmVkIGZyb20gc3RvcmFnZS5cbiAgICAvLyBUaGlzIGlzIGltcG9ydGFudCBmb3IgdGhlIHJlYXV0aGVudGljYXRlV2l0aFJlZGlyZWN0KCkgZmxvdy5cbiAgICBpZiAoXG4gICAgICB0aGlzLnJlZGlyZWN0VXNlciAmJlxuICAgICAgdGhpcy5yZWRpcmVjdFVzZXIuX3JlZGlyZWN0RXZlbnRJZCA9PT0gZnV0dXJlQ3VycmVudFVzZXIuX3JlZGlyZWN0RXZlbnRJZFxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuZGlyZWN0bHlTZXRDdXJyZW50VXNlcihmdXR1cmVDdXJyZW50VXNlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVsb2FkQW5kU2V0Q3VycmVudFVzZXJPckNsZWFyKGZ1dHVyZUN1cnJlbnRVc2VyKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdHJ5UmVkaXJlY3RTaWduSW4oXG4gICAgcmVkaXJlY3RSZXNvbHZlcjogUG9wdXBSZWRpcmVjdFJlc29sdmVyXG4gICk6IFByb21pc2U8VXNlckNyZWRlbnRpYWwgfCBudWxsPiB7XG4gICAgLy8gVGhlIHJlZGlyZWN0IHVzZXIgbmVlZHMgdG8gYmUgY2hlY2tlZCAoYW5kIHNpZ25lZCBpbiBpZiBhdmFpbGFibGUpXG4gICAgLy8gZHVyaW5nIGF1dGggaW5pdGlhbGl6YXRpb24uIEFsbCBvZiB0aGUgbm9ybWFsIHNpZ24gaW4gYW5kIGxpbmsvcmVhdXRoXG4gICAgLy8gZmxvd3MgY2FsbCBiYWNrIGludG8gYXV0aCBhbmQgcHVzaCB0aGluZ3Mgb250byB0aGUgcHJvbWlzZSBxdWV1ZS4gV2VcbiAgICAvLyBuZWVkIHRvIGF3YWl0IHRoZSByZXN1bHQgb2YgdGhlIHJlZGlyZWN0IHNpZ24gaW4gKmluc2lkZSB0aGUgcHJvbWlzZVxuICAgIC8vIHF1ZXVlKi4gVGhpcyBwcmVzZW50cyBhIHByb2JsZW06IHdlIHJ1biBpbnRvIGRlYWRsb2NrLiBTZWU6XG4gICAgLy8gICAg4pSMPiBbSW5pdGlhbGl6YXRpb25dIOKUgOKUgOKUgOKUgOKUgOKUkFxuICAgIC8vICAgIOKUjD4gWzxvdGhlciBxdWV1ZSB0YXNrcz5dIOKUglxuICAgIC8vICAgIOKUlOKUgCBbZ2V0UmVkaXJlY3RSZXN1bHRdIDzilIDilJhcbiAgICAvLyAgICB3aGVyZSBbXSBhcmUgdGFza3Mgb24gdGhlIHF1ZXVlIGFuZCBhcnJvd3MgZGVub3RlIGF3YWl0c1xuICAgIC8vIEluaXRpYWxpemF0aW9uIHdpbGwgbmV2ZXIgY29tcGxldGUgYmVjYXVzZSBpdCdzIHdhaXRpbmcgb24gc29tZXRoaW5nXG4gICAgLy8gdGhhdCdzIHdhaXRpbmcgZm9yIGluaXRpYWxpemF0aW9uIHRvIGNvbXBsZXRlIVxuICAgIC8vXG4gICAgLy8gSW5zdGVhZCwgdGhpcyBtZXRob2QgY2FsbHMgZ2V0UmVkaXJlY3RSZXN1bHQoKSAoc3RvcmVkIGluXG4gICAgLy8gX2NvbXBsZXRlUmVkaXJlY3RGbikgd2l0aCBhbiBvcHRpb25hbCBwYXJhbWV0ZXIgdGhhdCBpbnN0cnVjdHMgYWxsIG9mXG4gICAgLy8gdGhlIHVuZGVybHlpbmcgYXV0aCBvcGVyYXRpb25zIHRvIHNraXAgYW55dGhpbmcgdGhhdCBtdXRhdGVzIGF1dGggc3RhdGUuXG5cbiAgICBsZXQgcmVzdWx0OiBVc2VyQ3JlZGVudGlhbCB8IG51bGwgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICAvLyBXZSBrbm93IHRoaXMuX3BvcHVwUmVkaXJlY3RSZXNvbHZlciBpcyBzZXQgc2luY2UgcmVkaXJlY3RSZXNvbHZlclxuICAgICAgLy8gaXMgcGFzc2VkIGluLiBUaGUgX2NvbXBsZXRlUmVkaXJlY3RGbiBleHBlY3RzIHRoZSB1bndyYXBwZWQgZXh0ZXJuLlxuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5fcG9wdXBSZWRpcmVjdFJlc29sdmVyIS5fY29tcGxldGVSZWRpcmVjdEZuKFxuICAgICAgICB0aGlzLFxuICAgICAgICByZWRpcmVjdFJlc29sdmVyLFxuICAgICAgICB0cnVlXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIFN3YWxsb3cgYW55IGVycm9ycyBoZXJlOyB0aGUgY29kZSBjYW4gcmV0cmlldmUgdGhlbSBpblxuICAgICAgLy8gZ2V0UmVkaXJlY3RSZXN1bHQoKS5cbiAgICAgIGF3YWl0IHRoaXMuX3NldFJlZGlyZWN0VXNlcihudWxsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWxvYWRBbmRTZXRDdXJyZW50VXNlck9yQ2xlYXIoXG4gICAgdXNlcjogVXNlckludGVybmFsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBfcmVsb2FkV2l0aG91dFNhdmluZyh1c2VyKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoXG4gICAgICAgIChlIGFzIEZpcmViYXNlRXJyb3IpPy5jb2RlICE9PVxuICAgICAgICBgYXV0aC8ke0F1dGhFcnJvckNvZGUuTkVUV09SS19SRVFVRVNUX0ZBSUxFRH1gXG4gICAgICApIHtcbiAgICAgICAgLy8gU29tZXRoaW5nJ3Mgd3Jvbmcgd2l0aCB0aGUgdXNlcidzIHRva2VuLiBMb2cgdGhlbSBvdXQgYW5kIHJlbW92ZVxuICAgICAgICAvLyB0aGVtIGZyb20gc3RvcmFnZVxuICAgICAgICByZXR1cm4gdGhpcy5kaXJlY3RseVNldEN1cnJlbnRVc2VyKG51bGwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmRpcmVjdGx5U2V0Q3VycmVudFVzZXIodXNlcik7XG4gIH1cblxuICB1c2VEZXZpY2VMYW5ndWFnZSgpOiB2b2lkIHtcbiAgICB0aGlzLmxhbmd1YWdlQ29kZSA9IF9nZXRVc2VyTGFuZ3VhZ2UoKTtcbiAgfVxuXG4gIGFzeW5jIF9kZWxldGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5fZGVsZXRlZCA9IHRydWU7XG4gIH1cblxuICBhc3luYyB1cGRhdGVDdXJyZW50VXNlcih1c2VyRXh0ZXJuOiBVc2VyIHwgbnVsbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmFwcCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IodGhpcylcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIFRoZSBwdWJsaWMgdXBkYXRlQ3VycmVudFVzZXIgbWV0aG9kIG5lZWRzIHRvIG1ha2UgYSBjb3B5IG9mIHRoZSB1c2VyLFxuICAgIC8vIGFuZCBhbHNvIGNoZWNrIHRoYXQgdGhlIHByb2plY3QgbWF0Y2hlc1xuICAgIGNvbnN0IHVzZXIgPSB1c2VyRXh0ZXJuXG4gICAgICA/IChnZXRNb2R1bGFySW5zdGFuY2UodXNlckV4dGVybikgYXMgVXNlckludGVybmFsKVxuICAgICAgOiBudWxsO1xuICAgIGlmICh1c2VyKSB7XG4gICAgICBfYXNzZXJ0KFxuICAgICAgICB1c2VyLmF1dGguY29uZmlnLmFwaUtleSA9PT0gdGhpcy5jb25maWcuYXBpS2V5LFxuICAgICAgICB0aGlzLFxuICAgICAgICBBdXRoRXJyb3JDb2RlLklOVkFMSURfQVVUSFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3VwZGF0ZUN1cnJlbnRVc2VyKHVzZXIgJiYgdXNlci5fY2xvbmUodGhpcykpO1xuICB9XG5cbiAgYXN5bmMgX3VwZGF0ZUN1cnJlbnRVc2VyKFxuICAgIHVzZXI6IFVzZXIgfCBudWxsLFxuICAgIHNraXBCZWZvcmVTdGF0ZUNhbGxiYWNrczogYm9vbGVhbiA9IGZhbHNlXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLl9kZWxldGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh1c2VyKSB7XG4gICAgICBfYXNzZXJ0KFxuICAgICAgICB0aGlzLnRlbmFudElkID09PSB1c2VyLnRlbmFudElkLFxuICAgICAgICB0aGlzLFxuICAgICAgICBBdXRoRXJyb3JDb2RlLlRFTkFOVF9JRF9NSVNNQVRDSFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIXNraXBCZWZvcmVTdGF0ZUNhbGxiYWNrcykge1xuICAgICAgYXdhaXQgdGhpcy5iZWZvcmVTdGF0ZVF1ZXVlLnJ1bk1pZGRsZXdhcmUodXNlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucXVldWUoYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgdGhpcy5kaXJlY3RseVNldEN1cnJlbnRVc2VyKHVzZXIgYXMgVXNlckludGVybmFsIHwgbnVsbCk7XG4gICAgICB0aGlzLm5vdGlmeUF1dGhMaXN0ZW5lcnMoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIHNpZ25PdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKHRoaXMuYXBwKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcih0aGlzKVxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gUnVuIGZpcnN0LCB0byBibG9jayBfc2V0UmVkaXJlY3RVc2VyKCkgaWYgYW55IGNhbGxiYWNrcyBmYWlsLlxuICAgIGF3YWl0IHRoaXMuYmVmb3JlU3RhdGVRdWV1ZS5ydW5NaWRkbGV3YXJlKG51bGwpO1xuICAgIC8vIENsZWFyIHRoZSByZWRpcmVjdCB1c2VyIHdoZW4gc2lnbk91dCBpcyBjYWxsZWRcbiAgICBpZiAodGhpcy5yZWRpcmVjdFBlcnNpc3RlbmNlTWFuYWdlciB8fCB0aGlzLl9wb3B1cFJlZGlyZWN0UmVzb2x2ZXIpIHtcbiAgICAgIGF3YWl0IHRoaXMuX3NldFJlZGlyZWN0VXNlcihudWxsKTtcbiAgICB9XG5cbiAgICAvLyBQcmV2ZW50IGNhbGxiYWNrcyBmcm9tIGJlaW5nIGNhbGxlZCBhZ2FpbiBpbiBfdXBkYXRlQ3VycmVudFVzZXIsIGFzXG4gICAgLy8gdGhleSB3ZXJlIGFscmVhZHkgY2FsbGVkIGluIHRoZSBmaXJzdCBsaW5lLlxuICAgIHJldHVybiB0aGlzLl91cGRhdGVDdXJyZW50VXNlcihudWxsLCAvKiBza2lwQmVmb3JlU3RhdGVDYWxsYmFja3MgKi8gdHJ1ZSk7XG4gIH1cblxuICBzZXRQZXJzaXN0ZW5jZShwZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAodGhpcy5hcHApKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKHRoaXMpXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5xdWV1ZShhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2Uuc2V0UGVyc2lzdGVuY2UoX2dldEluc3RhbmNlKHBlcnNpc3RlbmNlKSk7XG4gICAgfSk7XG4gIH1cblxuICBfZ2V0UmVjYXB0Y2hhQ29uZmlnKCk6IFJlY2FwdGNoYUNvbmZpZyB8IG51bGwge1xuICAgIGlmICh0aGlzLnRlbmFudElkID09IG51bGwpIHtcbiAgICAgIHJldHVybiB0aGlzLl9hZ2VudFJlY2FwdGNoYUNvbmZpZztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3RlbmFudFJlY2FwdGNoYUNvbmZpZ3NbdGhpcy50ZW5hbnRJZF07XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgdmFsaWRhdGVQYXNzd29yZChwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxQYXNzd29yZFZhbGlkYXRpb25TdGF0dXM+IHtcbiAgICBpZiAoIXRoaXMuX2dldFBhc3N3b3JkUG9saWN5SW50ZXJuYWwoKSkge1xuICAgICAgYXdhaXQgdGhpcy5fdXBkYXRlUGFzc3dvcmRQb2xpY3koKTtcbiAgICB9XG5cbiAgICAvLyBQYXNzd29yZCBwb2xpY3kgd2lsbCBiZSBkZWZpbmVkIGFmdGVyIGZldGNoaW5nLlxuICAgIGNvbnN0IHBhc3N3b3JkUG9saWN5OiBQYXNzd29yZFBvbGljeUludGVybmFsID1cbiAgICAgIHRoaXMuX2dldFBhc3N3b3JkUG9saWN5SW50ZXJuYWwoKSE7XG5cbiAgICAvLyBDaGVjayB0aGF0IHRoZSBwb2xpY3kgc2NoZW1hIHZlcnNpb24gaXMgc3VwcG9ydGVkIGJ5IHRoZSBTREsuXG4gICAgLy8gVE9ETzogVXBkYXRlIHRoaXMgbG9naWMgdG8gdXNlIGEgbWF4IHN1cHBvcnRlZCBwb2xpY3kgc2NoZW1hIHZlcnNpb24gb25jZSB3ZSBoYXZlIG11bHRpcGxlIHNjaGVtYSB2ZXJzaW9ucy5cbiAgICBpZiAoXG4gICAgICBwYXNzd29yZFBvbGljeS5zY2hlbWFWZXJzaW9uICE9PVxuICAgICAgdGhpcy5FWFBFQ1RFRF9QQVNTV09SRF9QT0xJQ1lfU0NIRU1BX1ZFUlNJT05cbiAgICApIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgdGhpcy5fZXJyb3JGYWN0b3J5LmNyZWF0ZShcbiAgICAgICAgICBBdXRoRXJyb3JDb2RlLlVOU1VQUE9SVEVEX1BBU1NXT1JEX1BPTElDWV9TQ0hFTUFfVkVSU0lPTixcbiAgICAgICAgICB7fVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBwYXNzd29yZFBvbGljeS52YWxpZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKTtcbiAgfVxuXG4gIF9nZXRQYXNzd29yZFBvbGljeUludGVybmFsKCk6IFBhc3N3b3JkUG9saWN5SW50ZXJuYWwgfCBudWxsIHtcbiAgICBpZiAodGhpcy50ZW5hbnRJZCA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3Byb2plY3RQYXNzd29yZFBvbGljeTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3RlbmFudFBhc3N3b3JkUG9saWNpZXNbdGhpcy50ZW5hbnRJZF07XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgX3VwZGF0ZVBhc3N3b3JkUG9saWN5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2dldFBhc3N3b3JkUG9saWN5KHRoaXMpO1xuXG4gICAgY29uc3QgcGFzc3dvcmRQb2xpY3k6IFBhc3N3b3JkUG9saWN5SW50ZXJuYWwgPSBuZXcgUGFzc3dvcmRQb2xpY3lJbXBsKFxuICAgICAgcmVzcG9uc2VcbiAgICApO1xuXG4gICAgaWYgKHRoaXMudGVuYW50SWQgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuX3Byb2plY3RQYXNzd29yZFBvbGljeSA9IHBhc3N3b3JkUG9saWN5O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl90ZW5hbnRQYXNzd29yZFBvbGljaWVzW3RoaXMudGVuYW50SWRdID0gcGFzc3dvcmRQb2xpY3k7XG4gICAgfVxuICB9XG5cbiAgX2dldFBlcnNpc3RlbmNlVHlwZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2UucGVyc2lzdGVuY2UudHlwZTtcbiAgfVxuXG4gIF9nZXRQZXJzaXN0ZW5jZSgpOiBQZXJzaXN0ZW5jZUludGVybmFsIHtcbiAgICByZXR1cm4gdGhpcy5hc3NlcnRlZFBlcnNpc3RlbmNlLnBlcnNpc3RlbmNlO1xuICB9XG5cbiAgX3VwZGF0ZUVycm9yTWFwKGVycm9yTWFwOiBBdXRoRXJyb3JNYXApOiB2b2lkIHtcbiAgICB0aGlzLl9lcnJvckZhY3RvcnkgPSBuZXcgRXJyb3JGYWN0b3J5PEF1dGhFcnJvckNvZGUsIEF1dGhFcnJvclBhcmFtcz4oXG4gICAgICAnYXV0aCcsXG4gICAgICAnRmlyZWJhc2UnLFxuICAgICAgKGVycm9yTWFwIGFzIEVycm9yTWFwUmV0cmlldmVyKSgpXG4gICAgKTtcbiAgfVxuXG4gIG9uQXV0aFN0YXRlQ2hhbmdlZChcbiAgICBuZXh0T3JPYnNlcnZlcjogTmV4dE9yT2JzZXJ2ZXI8VXNlcj4sXG4gICAgZXJyb3I/OiBFcnJvckZuLFxuICAgIGNvbXBsZXRlZD86IENvbXBsZXRlRm5cbiAgKTogVW5zdWJzY3JpYmUge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdGVyU3RhdGVMaXN0ZW5lcihcbiAgICAgIHRoaXMuYXV0aFN0YXRlU3Vic2NyaXB0aW9uLFxuICAgICAgbmV4dE9yT2JzZXJ2ZXIsXG4gICAgICBlcnJvcixcbiAgICAgIGNvbXBsZXRlZFxuICAgICk7XG4gIH1cblxuICBiZWZvcmVBdXRoU3RhdGVDaGFuZ2VkKFxuICAgIGNhbGxiYWNrOiAodXNlcjogVXNlciB8IG51bGwpID0+IHZvaWQgfCBQcm9taXNlPHZvaWQ+LFxuICAgIG9uQWJvcnQ/OiAoKSA9PiB2b2lkXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICByZXR1cm4gdGhpcy5iZWZvcmVTdGF0ZVF1ZXVlLnB1c2hDYWxsYmFjayhjYWxsYmFjaywgb25BYm9ydCk7XG4gIH1cblxuICBvbklkVG9rZW5DaGFuZ2VkKFxuICAgIG5leHRPck9ic2VydmVyOiBOZXh0T3JPYnNlcnZlcjxVc2VyPixcbiAgICBlcnJvcj86IEVycm9yRm4sXG4gICAgY29tcGxldGVkPzogQ29tcGxldGVGblxuICApOiBVbnN1YnNjcmliZSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJTdGF0ZUxpc3RlbmVyKFxuICAgICAgdGhpcy5pZFRva2VuU3Vic2NyaXB0aW9uLFxuICAgICAgbmV4dE9yT2JzZXJ2ZXIsXG4gICAgICBlcnJvcixcbiAgICAgIGNvbXBsZXRlZFxuICAgICk7XG4gIH1cblxuICBhdXRoU3RhdGVSZWFkeSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKHRoaXMuY3VycmVudFVzZXIpIHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgdW5zdWJzY3JpYmUgPSB0aGlzLm9uQXV0aFN0YXRlQ2hhbmdlZCgoKSA9PiB7XG4gICAgICAgICAgdW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sIHJlamVjdCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV2b2tlcyB0aGUgZ2l2ZW4gYWNjZXNzIHRva2VuLiBDdXJyZW50bHkgb25seSBzdXBwb3J0cyBBcHBsZSBPQXV0aCBhY2Nlc3MgdG9rZW5zLlxuICAgKi9cbiAgYXN5bmMgcmV2b2tlQWNjZXNzVG9rZW4odG9rZW46IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICBjb25zdCBpZFRva2VuID0gYXdhaXQgdGhpcy5jdXJyZW50VXNlci5nZXRJZFRva2VuKCk7XG4gICAgICAvLyBHZW5lcmFsaXplIHRoaXMgdG8gYWNjZXB0IG90aGVyIHByb3ZpZGVycyBvbmNlIHN1cHBvcnRlZC5cbiAgICAgIGNvbnN0IHJlcXVlc3Q6IFJldm9rZVRva2VuUmVxdWVzdCA9IHtcbiAgICAgICAgcHJvdmlkZXJJZDogJ2FwcGxlLmNvbScsXG4gICAgICAgIHRva2VuVHlwZTogVG9rZW5UeXBlLkFDQ0VTU19UT0tFTixcbiAgICAgICAgdG9rZW4sXG4gICAgICAgIGlkVG9rZW5cbiAgICAgIH07XG4gICAgICBpZiAodGhpcy50ZW5hbnRJZCAhPSBudWxsKSB7XG4gICAgICAgIHJlcXVlc3QudGVuYW50SWQgPSB0aGlzLnRlbmFudElkO1xuICAgICAgfVxuICAgICAgYXdhaXQgcmV2b2tlVG9rZW4odGhpcywgcmVxdWVzdCk7XG4gICAgfVxuICB9XG5cbiAgdG9KU09OKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFwaUtleTogdGhpcy5jb25maWcuYXBpS2V5LFxuICAgICAgYXV0aERvbWFpbjogdGhpcy5jb25maWcuYXV0aERvbWFpbixcbiAgICAgIGFwcE5hbWU6IHRoaXMubmFtZSxcbiAgICAgIGN1cnJlbnRVc2VyOiB0aGlzLl9jdXJyZW50VXNlcj8udG9KU09OKClcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgX3NldFJlZGlyZWN0VXNlcihcbiAgICB1c2VyOiBVc2VySW50ZXJuYWwgfCBudWxsLFxuICAgIHBvcHVwUmVkaXJlY3RSZXNvbHZlcj86IFBvcHVwUmVkaXJlY3RSZXNvbHZlclxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZWRpcmVjdE1hbmFnZXIgPSBhd2FpdCB0aGlzLmdldE9ySW5pdFJlZGlyZWN0UGVyc2lzdGVuY2VNYW5hZ2VyKFxuICAgICAgcG9wdXBSZWRpcmVjdFJlc29sdmVyXG4gICAgKTtcbiAgICByZXR1cm4gdXNlciA9PT0gbnVsbFxuICAgICAgPyByZWRpcmVjdE1hbmFnZXIucmVtb3ZlQ3VycmVudFVzZXIoKVxuICAgICAgOiByZWRpcmVjdE1hbmFnZXIuc2V0Q3VycmVudFVzZXIodXNlcik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldE9ySW5pdFJlZGlyZWN0UGVyc2lzdGVuY2VNYW5hZ2VyKFxuICAgIHBvcHVwUmVkaXJlY3RSZXNvbHZlcj86IFBvcHVwUmVkaXJlY3RSZXNvbHZlclxuICApOiBQcm9taXNlPFBlcnNpc3RlbmNlVXNlck1hbmFnZXI+IHtcbiAgICBpZiAoIXRoaXMucmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIpIHtcbiAgICAgIGNvbnN0IHJlc29sdmVyOiBQb3B1cFJlZGlyZWN0UmVzb2x2ZXJJbnRlcm5hbCB8IG51bGwgPVxuICAgICAgICAocG9wdXBSZWRpcmVjdFJlc29sdmVyICYmIF9nZXRJbnN0YW5jZShwb3B1cFJlZGlyZWN0UmVzb2x2ZXIpKSB8fFxuICAgICAgICB0aGlzLl9wb3B1cFJlZGlyZWN0UmVzb2x2ZXI7XG4gICAgICBfYXNzZXJ0KHJlc29sdmVyLCB0aGlzLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICAgIHRoaXMucmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIgPSBhd2FpdCBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyLmNyZWF0ZShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgW19nZXRJbnN0YW5jZShyZXNvbHZlci5fcmVkaXJlY3RQZXJzaXN0ZW5jZSldLFxuICAgICAgICBLZXlOYW1lLlJFRElSRUNUX1VTRVJcbiAgICAgICk7XG4gICAgICB0aGlzLnJlZGlyZWN0VXNlciA9XG4gICAgICAgIGF3YWl0IHRoaXMucmVkaXJlY3RQZXJzaXN0ZW5jZU1hbmFnZXIuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5yZWRpcmVjdFBlcnNpc3RlbmNlTWFuYWdlcjtcbiAgfVxuXG4gIGFzeW5jIF9yZWRpcmVjdFVzZXJGb3JJZChpZDogc3RyaW5nKTogUHJvbWlzZTxVc2VySW50ZXJuYWwgfCBudWxsPiB7XG4gICAgLy8gTWFrZSBzdXJlIHdlJ3ZlIGNsZWFyZWQgYW55IHBlbmRpbmcgcGVyc2lzdGVuY2UgYWN0aW9ucyBpZiB3ZSdyZSBub3QgaW5cbiAgICAvLyB0aGUgaW5pdGlhbGl6ZXJcbiAgICBpZiAodGhpcy5faXNJbml0aWFsaXplZCkge1xuICAgICAgYXdhaXQgdGhpcy5xdWV1ZShhc3luYyAoKSA9PiB7fSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2N1cnJlbnRVc2VyPy5fcmVkaXJlY3RFdmVudElkID09PSBpZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRVc2VyO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnJlZGlyZWN0VXNlcj8uX3JlZGlyZWN0RXZlbnRJZCA9PT0gaWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlZGlyZWN0VXNlcjtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIF9wZXJzaXN0VXNlcklmQ3VycmVudCh1c2VyOiBVc2VySW50ZXJuYWwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodXNlciA9PT0gdGhpcy5jdXJyZW50VXNlcikge1xuICAgICAgcmV0dXJuIHRoaXMucXVldWUoYXN5bmMgKCkgPT4gdGhpcy5kaXJlY3RseVNldEN1cnJlbnRVc2VyKHVzZXIpKTtcbiAgICB9XG4gIH1cblxuICAvKiogTm90aWZpZXMgbGlzdGVuZXJzIG9ubHkgaWYgdGhlIHVzZXIgaXMgY3VycmVudCAqL1xuICBfbm90aWZ5TGlzdGVuZXJzSWZDdXJyZW50KHVzZXI6IFVzZXJJbnRlcm5hbCk6IHZvaWQge1xuICAgIGlmICh1c2VyID09PSB0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICB0aGlzLm5vdGlmeUF1dGhMaXN0ZW5lcnMoKTtcbiAgICB9XG4gIH1cblxuICBfa2V5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMuY29uZmlnLmF1dGhEb21haW59OiR7dGhpcy5jb25maWcuYXBpS2V5fToke3RoaXMubmFtZX1gO1xuICB9XG5cbiAgX3N0YXJ0UHJvYWN0aXZlUmVmcmVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLmlzUHJvYWN0aXZlUmVmcmVzaEVuYWJsZWQgPSB0cnVlO1xuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICB0aGlzLl9jdXJyZW50VXNlci5fc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfVxuICB9XG5cbiAgX3N0b3BQcm9hY3RpdmVSZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMuaXNQcm9hY3RpdmVSZWZyZXNoRW5hYmxlZCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmN1cnJlbnRVc2VyKSB7XG4gICAgICB0aGlzLl9jdXJyZW50VXNlci5fc3RvcFByb2FjdGl2ZVJlZnJlc2goKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmV0dXJucyB0aGUgY3VycmVudCB1c2VyIGNhc3QgYXMgdGhlIGludGVybmFsIHR5cGUgKi9cbiAgZ2V0IF9jdXJyZW50VXNlcigpOiBVc2VySW50ZXJuYWwge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRVc2VyIGFzIFVzZXJJbnRlcm5hbDtcbiAgfVxuXG4gIHByaXZhdGUgbm90aWZ5QXV0aExpc3RlbmVycygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX2lzSW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlkVG9rZW5TdWJzY3JpcHRpb24ubmV4dCh0aGlzLmN1cnJlbnRVc2VyKTtcblxuICAgIGNvbnN0IGN1cnJlbnRVaWQgPSB0aGlzLmN1cnJlbnRVc2VyPy51aWQgPz8gbnVsbDtcbiAgICBpZiAodGhpcy5sYXN0Tm90aWZpZWRVaWQgIT09IGN1cnJlbnRVaWQpIHtcbiAgICAgIHRoaXMubGFzdE5vdGlmaWVkVWlkID0gY3VycmVudFVpZDtcbiAgICAgIHRoaXMuYXV0aFN0YXRlU3Vic2NyaXB0aW9uLm5leHQodGhpcy5jdXJyZW50VXNlcik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlclN0YXRlTGlzdGVuZXIoXG4gICAgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb248VXNlcj4sXG4gICAgbmV4dE9yT2JzZXJ2ZXI6IE5leHRPck9ic2VydmVyPFVzZXI+LFxuICAgIGVycm9yPzogRXJyb3JGbixcbiAgICBjb21wbGV0ZWQ/OiBDb21wbGV0ZUZuXG4gICk6IFVuc3Vic2NyaWJlIHtcbiAgICBpZiAodGhpcy5fZGVsZXRlZCkge1xuICAgICAgcmV0dXJuICgpID0+IHt9O1xuICAgIH1cblxuICAgIGNvbnN0IGNiID1cbiAgICAgIHR5cGVvZiBuZXh0T3JPYnNlcnZlciA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICA/IG5leHRPck9ic2VydmVyXG4gICAgICAgIDogbmV4dE9yT2JzZXJ2ZXIubmV4dC5iaW5kKG5leHRPck9ic2VydmVyKTtcblxuICAgIGxldCBpc1Vuc3Vic2NyaWJlZCA9IGZhbHNlO1xuXG4gICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2lzSW5pdGlhbGl6ZWRcbiAgICAgID8gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIDogdGhpcy5faW5pdGlhbGl6YXRpb25Qcm9taXNlO1xuICAgIF9hc3NlcnQocHJvbWlzZSwgdGhpcywgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgLy8gVGhlIGNhbGxiYWNrIG5lZWRzIHRvIGJlIGNhbGxlZCBhc3luY2hyb25vdXNseSBwZXIgdGhlIHNwZWMuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICAgIHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICBpZiAoaXNVbnN1YnNjcmliZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY2IodGhpcy5jdXJyZW50VXNlcik7XG4gICAgfSk7XG5cbiAgICBpZiAodHlwZW9mIG5leHRPck9ic2VydmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjb25zdCB1bnN1YnNjcmliZSA9IHN1YnNjcmlwdGlvbi5hZGRPYnNlcnZlcihcbiAgICAgICAgbmV4dE9yT2JzZXJ2ZXIsXG4gICAgICAgIGVycm9yLFxuICAgICAgICBjb21wbGV0ZWRcbiAgICAgICk7XG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpc1Vuc3Vic2NyaWJlZCA9IHRydWU7XG4gICAgICAgIHVuc3Vic2NyaWJlKCk7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB1bnN1YnNjcmliZSA9IHN1YnNjcmlwdGlvbi5hZGRPYnNlcnZlcihuZXh0T3JPYnNlcnZlcik7XG4gICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICBpc1Vuc3Vic2NyaWJlZCA9IHRydWU7XG4gICAgICAgIHVuc3Vic2NyaWJlKCk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbnByb3RlY3RlZCAoZnJvbSByYWNlIGNvbmRpdGlvbnMpIG1ldGhvZCB0byBzZXQgdGhlIGN1cnJlbnQgdXNlci4gVGhpc1xuICAgKiBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSB3aXRoaW4gYSBxdWV1ZWQgY2FsbGJhY2suIFRoaXMgaXMgbmVjZXNzYXJ5XG4gICAqIGJlY2F1c2UgdGhlIHF1ZXVlIHNob3VsZG4ndCByZWx5IG9uIGFub3RoZXIgcXVldWVkIGNhbGxiYWNrLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBkaXJlY3RseVNldEN1cnJlbnRVc2VyKFxuICAgIHVzZXI6IFVzZXJJbnRlcm5hbCB8IG51bGxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuY3VycmVudFVzZXIgJiYgdGhpcy5jdXJyZW50VXNlciAhPT0gdXNlcikge1xuICAgICAgdGhpcy5fY3VycmVudFVzZXIuX3N0b3BQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfVxuICAgIGlmICh1c2VyICYmIHRoaXMuaXNQcm9hY3RpdmVSZWZyZXNoRW5hYmxlZCkge1xuICAgICAgdXNlci5fc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50VXNlciA9IHVzZXI7XG5cbiAgICBpZiAodXNlcikge1xuICAgICAgYXdhaXQgdGhpcy5hc3NlcnRlZFBlcnNpc3RlbmNlLnNldEN1cnJlbnRVc2VyKHVzZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCB0aGlzLmFzc2VydGVkUGVyc2lzdGVuY2UucmVtb3ZlQ3VycmVudFVzZXIoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHF1ZXVlKGFjdGlvbjogQXN5bmNBY3Rpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBJbiBjYXNlIHNvbWV0aGluZyBlcnJvcnMsIHRoZSBjYWxsYmFjayBzdGlsbCBzaG91bGQgYmUgY2FsbGVkIGluIG9yZGVyXG4gICAgLy8gdG8ga2VlcCB0aGUgcHJvbWlzZSBjaGFpbiBhbGl2ZVxuICAgIHRoaXMub3BlcmF0aW9ucyA9IHRoaXMub3BlcmF0aW9ucy50aGVuKGFjdGlvbiwgYWN0aW9uKTtcbiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgYXNzZXJ0ZWRQZXJzaXN0ZW5jZSgpOiBQZXJzaXN0ZW5jZVVzZXJNYW5hZ2VyIHtcbiAgICBfYXNzZXJ0KHRoaXMucGVyc2lzdGVuY2VNYW5hZ2VyLCB0aGlzLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICByZXR1cm4gdGhpcy5wZXJzaXN0ZW5jZU1hbmFnZXI7XG4gIH1cblxuICBwcml2YXRlIGZyYW1ld29ya3M6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgY2xpZW50VmVyc2lvbjogc3RyaW5nO1xuICBfbG9nRnJhbWV3b3JrKGZyYW1ld29yazogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFmcmFtZXdvcmsgfHwgdGhpcy5mcmFtZXdvcmtzLmluY2x1ZGVzKGZyYW1ld29yaykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5mcmFtZXdvcmtzLnB1c2goZnJhbWV3b3JrKTtcblxuICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgc28gdGhhdCBcIkZpcmViYXNlQ29yZS13ZWIsRmlyZWJhc2VVSS13ZWJcIiBhbmRcbiAgICAvLyBcIkZpcmViYXNlVUktd2ViLEZpcmViYXNlQ29yZS13ZWJcIiBhcmVuJ3Qgdmlld2VkIGFzIGRpZmZlcmVudC5cbiAgICB0aGlzLmZyYW1ld29ya3Muc29ydCgpO1xuICAgIHRoaXMuY2xpZW50VmVyc2lvbiA9IF9nZXRDbGllbnRWZXJzaW9uKFxuICAgICAgdGhpcy5jb25maWcuY2xpZW50UGxhdGZvcm0sXG4gICAgICB0aGlzLl9nZXRGcmFtZXdvcmtzKClcbiAgICApO1xuICB9XG4gIF9nZXRGcmFtZXdvcmtzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5mcmFtZXdvcmtzO1xuICB9XG4gIGFzeW5jIF9nZXRBZGRpdGlvbmFsSGVhZGVycygpOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgICAvLyBBZGRpdGlvbmFsIGhlYWRlcnMgb24gZXZlcnkgcmVxdWVzdFxuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBbSHR0cEhlYWRlci5YX0NMSUVOVF9WRVJTSU9OXTogdGhpcy5jbGllbnRWZXJzaW9uXG4gICAgfTtcblxuICAgIGlmICh0aGlzLmFwcC5vcHRpb25zLmFwcElkKSB7XG4gICAgICBoZWFkZXJzW0h0dHBIZWFkZXIuWF9GSVJFQkFTRV9HTVBJRF0gPSB0aGlzLmFwcC5vcHRpb25zLmFwcElkO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBoZWFydGJlYXQgc2VydmljZSBleGlzdHMsIGFkZCB0aGUgaGVhcnRiZWF0IHN0cmluZ1xuICAgIGNvbnN0IGhlYXJ0YmVhdHNIZWFkZXIgPSBhd2FpdCB0aGlzLmhlYXJ0YmVhdFNlcnZpY2VQcm92aWRlclxuICAgICAgLmdldEltbWVkaWF0ZSh7XG4gICAgICAgIG9wdGlvbmFsOiB0cnVlXG4gICAgICB9KVxuICAgICAgPy5nZXRIZWFydGJlYXRzSGVhZGVyKCk7XG4gICAgaWYgKGhlYXJ0YmVhdHNIZWFkZXIpIHtcbiAgICAgIGhlYWRlcnNbSHR0cEhlYWRlci5YX0ZJUkVCQVNFX0NMSUVOVF0gPSBoZWFydGJlYXRzSGVhZGVyO1xuICAgIH1cblxuICAgIC8vIElmIHRoZSBBcHAgQ2hlY2sgc2VydmljZSBleGlzdHMsIGFkZCB0aGUgQXBwIENoZWNrIHRva2VuIGluIHRoZSBoZWFkZXJzXG4gICAgY29uc3QgYXBwQ2hlY2tUb2tlbiA9IGF3YWl0IHRoaXMuX2dldEFwcENoZWNrVG9rZW4oKTtcbiAgICBpZiAoYXBwQ2hlY2tUb2tlbikge1xuICAgICAgaGVhZGVyc1tIdHRwSGVhZGVyLlhfRklSRUJBU0VfQVBQX0NIRUNLXSA9IGFwcENoZWNrVG9rZW47XG4gICAgfVxuXG4gICAgcmV0dXJuIGhlYWRlcnM7XG4gIH1cblxuICBhc3luYyBfZ2V0QXBwQ2hlY2tUb2tlbigpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcCh0aGlzLmFwcCkgJiYgdGhpcy5hcHAuc2V0dGluZ3MuYXBwQ2hlY2tUb2tlbikge1xuICAgICAgcmV0dXJuIHRoaXMuYXBwLnNldHRpbmdzLmFwcENoZWNrVG9rZW47XG4gICAgfVxuICAgIGNvbnN0IGFwcENoZWNrVG9rZW5SZXN1bHQgPSBhd2FpdCB0aGlzLmFwcENoZWNrU2VydmljZVByb3ZpZGVyXG4gICAgICAuZ2V0SW1tZWRpYXRlKHsgb3B0aW9uYWw6IHRydWUgfSlcbiAgICAgID8uZ2V0VG9rZW4oKTtcbiAgICBpZiAoYXBwQ2hlY2tUb2tlblJlc3VsdD8uZXJyb3IpIHtcbiAgICAgIC8vIENvbnRleHQ6IGFwcENoZWNrLmdldFRva2VuKCkgd2lsbCBuZXZlciB0aHJvdyBldmVuIGlmIGFuIGVycm9yIGhhcHBlbmVkLlxuICAgICAgLy8gSW4gdGhlIGVycm9yIGNhc2UsIGEgZHVtbXkgdG9rZW4gd2lsbCBiZSByZXR1cm5lZCBhbG9uZyB3aXRoIGFuIGVycm9yIGZpZWxkIGRlc2NyaWJpbmdcbiAgICAgIC8vIHRoZSBlcnJvci4gSW4gZ2VuZXJhbCwgd2Ugc2hvdWxkbid0IGNhcmUgYWJvdXQgdGhlIGVycm9yIGNvbmRpdGlvbiBhbmQganVzdCB1c2VcbiAgICAgIC8vIHRoZSB0b2tlbiAoYWN0dWFsIG9yIGR1bW15KSB0byBzZW5kIHJlcXVlc3RzLlxuICAgICAgX2xvZ1dhcm4oXG4gICAgICAgIGBFcnJvciB3aGlsZSByZXRyaWV2aW5nIEFwcCBDaGVjayB0b2tlbjogJHthcHBDaGVja1Rva2VuUmVzdWx0LmVycm9yfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBhcHBDaGVja1Rva2VuUmVzdWx0Py50b2tlbjtcbiAgfVxufVxuXG4vKipcbiAqIE1ldGhvZCB0byBiZSB1c2VkIHRvIGNhc3QgZG93biB0byBvdXIgcHJpdmF0ZSBpbXBsZW1lbnRhdGlvbiBvZiBBdXRoLlxuICogSXQgd2lsbCBhbHNvIGhhbmRsZSB1bndyYXBwaW5nIGZyb20gdGhlIGNvbXBhdCB0eXBlIGlmIG5lY2Vzc2FyeVxuICpcbiAqIEBwYXJhbSBhdXRoIEF1dGggb2JqZWN0IHBhc3NlZCBpbiBmcm9tIGRldmVsb3BlclxuICovXG5leHBvcnQgZnVuY3Rpb24gX2Nhc3RBdXRoKGF1dGg6IEF1dGgpOiBBdXRoSW50ZXJuYWwge1xuICByZXR1cm4gZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpIGFzIEF1dGhJbnRlcm5hbDtcbn1cblxuLyoqIEhlbHBlciBjbGFzcyB0byB3cmFwIHN1YnNjcmliZXIgbG9naWMgKi9cbmNsYXNzIFN1YnNjcmlwdGlvbjxUPiB7XG4gIHByaXZhdGUgb2JzZXJ2ZXI6IE9ic2VydmVyPFQgfCBudWxsPiB8IG51bGwgPSBudWxsO1xuICByZWFkb25seSBhZGRPYnNlcnZlcjogU3Vic2NyaWJlPFQgfCBudWxsPiA9IGNyZWF0ZVN1YnNjcmliZShcbiAgICBvYnNlcnZlciA9PiAodGhpcy5vYnNlcnZlciA9IG9ic2VydmVyKVxuICApO1xuXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbCkge31cblxuICBnZXQgbmV4dCgpOiBOZXh0Rm48VCB8IG51bGw+IHtcbiAgICBfYXNzZXJ0KHRoaXMub2JzZXJ2ZXIsIHRoaXMuYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgcmV0dXJuIHRoaXMub2JzZXJ2ZXIubmV4dC5iaW5kKHRoaXMub2JzZXJ2ZXIpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW50ZXJmYWNlIEV4dGVybmFsSlNQcm92aWRlciB7XG4gIGxvYWRKUyh1cmw6IHN0cmluZyk6IFByb21pc2U8RXZlbnQ+O1xuICByZWNhcHRjaGFWMlNjcmlwdDogc3RyaW5nO1xuICByZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0OiBzdHJpbmc7XG4gIGdhcGlTY3JpcHQ6IHN0cmluZztcbn1cblxubGV0IGV4dGVybmFsSlNQcm92aWRlcjogRXh0ZXJuYWxKU1Byb3ZpZGVyID0ge1xuICBhc3luYyBsb2FkSlMoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gbG9hZCBleHRlcm5hbCBzY3JpcHRzJyk7XG4gIH0sXG5cbiAgcmVjYXB0Y2hhVjJTY3JpcHQ6ICcnLFxuICByZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0OiAnJyxcbiAgZ2FwaVNjcmlwdDogJydcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBfc2V0RXh0ZXJuYWxKU1Byb3ZpZGVyKHA6IEV4dGVybmFsSlNQcm92aWRlcik6IHZvaWQge1xuICBleHRlcm5hbEpTUHJvdmlkZXIgPSBwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2xvYWRKUyh1cmw6IHN0cmluZyk6IFByb21pc2U8RXZlbnQ+IHtcbiAgcmV0dXJuIGV4dGVybmFsSlNQcm92aWRlci5sb2FkSlModXJsKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9yZWNhcHRjaGFWMlNjcmlwdFVybCgpOiBzdHJpbmcge1xuICByZXR1cm4gZXh0ZXJuYWxKU1Byb3ZpZGVyLnJlY2FwdGNoYVYyU2NyaXB0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX3JlY2FwdGNoYUVudGVycHJpc2VTY3JpcHRVcmwoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGV4dGVybmFsSlNQcm92aWRlci5yZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2dhcGlTY3JpcHRVcmwoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGV4dGVybmFsSlNQcm92aWRlci5nYXBpU2NyaXB0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2dlbmVyYXRlQ2FsbGJhY2tOYW1lKHByZWZpeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBfXyR7cHJlZml4fSR7TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDAwMCl9YDtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBSZWNhcHRjaGFQYXJhbWV0ZXJzIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7XG4gIFJlY2FwdGNoYSxcbiAgR3JlQ0FQVENIQVRvcExldmVsLFxuICBHcmVDQVBUQ0hBUmVuZGVyT3B0aW9uLFxuICBHcmVDQVBUQ0hBXG59IGZyb20gJy4vcmVjYXB0Y2hhJztcblxuZXhwb3J0IGNvbnN0IF9TT0xWRV9USU1FX01TID0gNTAwO1xuZXhwb3J0IGNvbnN0IF9FWFBJUkFUSU9OX1RJTUVfTVMgPSA2MF8wMDA7XG5leHBvcnQgY29uc3QgX1dJREdFVF9JRF9TVEFSVCA9IDFfMDAwXzAwMF8wMDBfMDAwO1xuXG5leHBvcnQgaW50ZXJmYWNlIFdpZGdldCB7XG4gIGdldFJlc3BvbnNlOiAoKSA9PiBzdHJpbmcgfCBudWxsO1xuICBkZWxldGU6ICgpID0+IHZvaWQ7XG4gIGV4ZWN1dGU6ICgpID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBjbGFzcyBNb2NrUmVDYXB0Y2hhIGltcGxlbWVudHMgUmVjYXB0Y2hhIHtcbiAgcHJpdmF0ZSBjb3VudGVyID0gX1dJREdFVF9JRF9TVEFSVDtcbiAgX3dpZGdldHMgPSBuZXcgTWFwPG51bWJlciwgV2lkZ2V0PigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgYXV0aDogQXV0aEludGVybmFsKSB7fVxuXG4gIHJlbmRlcihcbiAgICBjb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIHBhcmFtZXRlcnM/OiBSZWNhcHRjaGFQYXJhbWV0ZXJzXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgaWQgPSB0aGlzLmNvdW50ZXI7XG4gICAgdGhpcy5fd2lkZ2V0cy5zZXQoXG4gICAgICBpZCxcbiAgICAgIG5ldyBNb2NrV2lkZ2V0KGNvbnRhaW5lciwgdGhpcy5hdXRoLm5hbWUsIHBhcmFtZXRlcnMgfHwge30pXG4gICAgKTtcbiAgICB0aGlzLmNvdW50ZXIrKztcbiAgICByZXR1cm4gaWQ7XG4gIH1cblxuICByZXNldChvcHRXaWRnZXRJZD86IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGlkID0gb3B0V2lkZ2V0SWQgfHwgX1dJREdFVF9JRF9TVEFSVDtcbiAgICB2b2lkIHRoaXMuX3dpZGdldHMuZ2V0KGlkKT8uZGVsZXRlKCk7XG4gICAgdGhpcy5fd2lkZ2V0cy5kZWxldGUoaWQpO1xuICB9XG5cbiAgZ2V0UmVzcG9uc2Uob3B0V2lkZ2V0SWQ/OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGlkID0gb3B0V2lkZ2V0SWQgfHwgX1dJREdFVF9JRF9TVEFSVDtcbiAgICByZXR1cm4gdGhpcy5fd2lkZ2V0cy5nZXQoaWQpPy5nZXRSZXNwb25zZSgpIHx8ICcnO1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZShvcHRXaWRnZXRJZD86IG51bWJlciB8IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgaWQ6IG51bWJlciA9IChvcHRXaWRnZXRJZCBhcyBudW1iZXIpIHx8IF9XSURHRVRfSURfU1RBUlQ7XG4gICAgdm9pZCB0aGlzLl93aWRnZXRzLmdldChpZCk/LmV4ZWN1dGUoKTtcbiAgICByZXR1cm4gJyc7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1vY2tHcmVDQVBUQ0hBVG9wTGV2ZWwgaW1wbGVtZW50cyBHcmVDQVBUQ0hBVG9wTGV2ZWwge1xuICBlbnRlcnByaXNlOiBHcmVDQVBUQ0hBID0gbmV3IE1vY2tHcmVDQVBUQ0hBKCk7XG4gIHJlYWR5KGNhbGxiYWNrOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGV4ZWN1dGUoXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIF9zaXRlS2V5OiBzdHJpbmcsXG4gICAgX29wdGlvbnM6IHsgYWN0aW9uOiBzdHJpbmcgfVxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoJ3Rva2VuJyk7XG4gIH1cbiAgcmVuZGVyKFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBfY29udGFpbmVyOiBzdHJpbmcgfCBIVE1MRWxlbWVudCxcbiAgICBfcGFyYW1ldGVyczogR3JlQ0FQVENIQVJlbmRlck9wdGlvblxuICApOiBzdHJpbmcge1xuICAgIHJldHVybiAnJztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTW9ja0dyZUNBUFRDSEEgaW1wbGVtZW50cyBHcmVDQVBUQ0hBIHtcbiAgcmVhZHkoY2FsbGJhY2s6ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgZXhlY3V0ZShcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgX3NpdGVLZXk6IHN0cmluZyxcbiAgICBfb3B0aW9uczogeyBhY3Rpb246IHN0cmluZyB9XG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgndG9rZW4nKTtcbiAgfVxuICByZW5kZXIoXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIF9jb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIF9wYXJhbWV0ZXJzOiBHcmVDQVBUQ0hBUmVuZGVyT3B0aW9uXG4gICk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNb2NrV2lkZ2V0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXI6IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGlzVmlzaWJsZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSB0aW1lcklkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBkZWxldGVkID0gZmFsc2U7XG4gIHByaXZhdGUgcmVzcG9uc2VUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2xpY2tIYW5kbGVyID0gKCk6IHZvaWQgPT4ge1xuICAgIHRoaXMuZXhlY3V0ZSgpO1xuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNvbnRhaW5lck9ySWQ6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgIGFwcE5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBhcmFtczogUmVjYXB0Y2hhUGFyYW1ldGVyc1xuICApIHtcbiAgICBjb25zdCBjb250YWluZXIgPVxuICAgICAgdHlwZW9mIGNvbnRhaW5lck9ySWQgPT09ICdzdHJpbmcnXG4gICAgICAgID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY29udGFpbmVyT3JJZClcbiAgICAgICAgOiBjb250YWluZXJPcklkO1xuICAgIF9hc3NlcnQoY29udGFpbmVyLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SLCB7IGFwcE5hbWUgfSk7XG5cbiAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICB0aGlzLmlzVmlzaWJsZSA9IHRoaXMucGFyYW1zLnNpemUgIT09ICdpbnZpc2libGUnO1xuICAgIGlmICh0aGlzLmlzVmlzaWJsZSkge1xuICAgICAgdGhpcy5leGVjdXRlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5jbGlja0hhbmRsZXIpO1xuICAgIH1cbiAgfVxuXG4gIGdldFJlc3BvbnNlKCk6IHN0cmluZyB8IG51bGwge1xuICAgIHRoaXMuY2hlY2tJZkRlbGV0ZWQoKTtcbiAgICByZXR1cm4gdGhpcy5yZXNwb25zZVRva2VuO1xuICB9XG5cbiAgZGVsZXRlKCk6IHZvaWQge1xuICAgIHRoaXMuY2hlY2tJZkRlbGV0ZWQoKTtcbiAgICB0aGlzLmRlbGV0ZWQgPSB0cnVlO1xuICAgIGlmICh0aGlzLnRpbWVySWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVySWQpO1xuICAgICAgdGhpcy50aW1lcklkID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5jb250YWluZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmNsaWNrSGFuZGxlcik7XG4gIH1cblxuICBleGVjdXRlKCk6IHZvaWQge1xuICAgIHRoaXMuY2hlY2tJZkRlbGV0ZWQoKTtcbiAgICBpZiAodGhpcy50aW1lcklkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy50aW1lcklkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5yZXNwb25zZVRva2VuID0gZ2VuZXJhdGVSYW5kb21BbHBoYU51bWVyaWNTdHJpbmcoNTApO1xuICAgICAgY29uc3QgeyBjYWxsYmFjaywgJ2V4cGlyZWQtY2FsbGJhY2snOiBleHBpcmVkQ2FsbGJhY2sgfSA9IHRoaXMucGFyYW1zO1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY2FsbGJhY2sodGhpcy5yZXNwb25zZVRva2VuKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgIH1cblxuICAgICAgdGhpcy50aW1lcklkID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnRpbWVySWQgPSBudWxsO1xuICAgICAgICB0aGlzLnJlc3BvbnNlVG9rZW4gPSBudWxsO1xuICAgICAgICBpZiAoZXhwaXJlZENhbGxiYWNrKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGV4cGlyZWRDYWxsYmFjaygpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pc1Zpc2libGUpIHtcbiAgICAgICAgICB0aGlzLmV4ZWN1dGUoKTtcbiAgICAgICAgfVxuICAgICAgfSwgX0VYUElSQVRJT05fVElNRV9NUyk7XG4gICAgfSwgX1NPTFZFX1RJTUVfTVMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0lmRGVsZXRlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kZWxldGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlQ0FQVENIQSBtb2NrIHdhcyBhbHJlYWR5IGRlbGV0ZWQhJyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlUmFuZG9tQWxwaGFOdW1lcmljU3RyaW5nKGxlbjogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgY2hhcnMgPSBbXTtcbiAgY29uc3QgYWxsb3dlZENoYXJzID1cbiAgICAnMTIzNDU2Nzg5MGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVonO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgY2hhcnMucHVzaChcbiAgICAgIGFsbG93ZWRDaGFycy5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYWxsb3dlZENoYXJzLmxlbmd0aCkpXG4gICAgKTtcbiAgfVxuICByZXR1cm4gY2hhcnMuam9pbignJyk7XG59XG4iLCAiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjIgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgaXNFbnRlcnByaXNlLCBSZWNhcHRjaGFDb25maWcgfSBmcm9tICcuL3JlY2FwdGNoYSc7XG5pbXBvcnQgeyBnZXRSZWNhcHRjaGFDb25maWcgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vcmVjYXB0Y2hhJztcbmltcG9ydCB7XG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYVZlcnNpb24sXG4gIFJlY2FwdGNoYUFjdGlvbk5hbWUsXG4gIFJlY2FwdGNoYUF1dGhQcm92aWRlcixcbiAgRW5mb3JjZW1lbnRTdGF0ZVxufSBmcm9tICcuLi8uLi9hcGknO1xuXG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgKiBhcyBqc0hlbHBlcnMgZnJvbSAnLi4vbG9hZF9qcyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgU3RhcnRQaG9uZU1mYUVucm9sbG1lbnRSZXF1ZXN0IH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9tZmEnO1xuaW1wb3J0IHsgU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3QgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IE1vY2tHcmVDQVBUQ0hBVG9wTGV2ZWwgfSBmcm9tICcuL3JlY2FwdGNoYV9tb2NrJztcblxuZXhwb3J0IGNvbnN0IFJFQ0FQVENIQV9FTlRFUlBSSVNFX1ZFUklGSUVSX1RZUEUgPSAncmVjYXB0Y2hhLWVudGVycHJpc2UnO1xuZXhwb3J0IGNvbnN0IEZBS0VfVE9LRU4gPSAnTk9fUkVDQVBUQ0hBJztcblxuZXhwb3J0IGNsYXNzIFJlY2FwdGNoYUVudGVycHJpc2VWZXJpZmllciB7XG4gIC8qKlxuICAgKiBJZGVudGlmaWVzIHRoZSB0eXBlIG9mIGFwcGxpY2F0aW9uIHZlcmlmaWVyIChlLmcuIFwicmVjYXB0Y2hhLWVudGVycHJpc2VcIikuXG4gICAqL1xuICByZWFkb25seSB0eXBlID0gUkVDQVBUQ0hBX0VOVEVSUFJJU0VfVkVSSUZJRVJfVFlQRTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbDtcblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGF1dGhFeHRlcm4gLSBUaGUgY29ycmVzcG9uZGluZyBGaXJlYmFzZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gICAqXG4gICAqL1xuICBjb25zdHJ1Y3RvcihhdXRoRXh0ZXJuOiBBdXRoKSB7XG4gICAgdGhpcy5hdXRoID0gX2Nhc3RBdXRoKGF1dGhFeHRlcm4pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGVzIHRoZSB2ZXJpZmljYXRpb24gcHJvY2Vzcy5cbiAgICpcbiAgICogQHJldHVybnMgQSBQcm9taXNlIGZvciBhIHRva2VuIHRoYXQgY2FuIGJlIHVzZWQgdG8gYXNzZXJ0IHRoZSB2YWxpZGl0eSBvZiBhIHJlcXVlc3QuXG4gICAqL1xuICBhc3luYyB2ZXJpZnkoXG4gICAgYWN0aW9uOiBzdHJpbmcgPSAndmVyaWZ5JyxcbiAgICBmb3JjZVJlZnJlc2ggPSBmYWxzZVxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGFzeW5jIGZ1bmN0aW9uIHJldHJpZXZlU2l0ZUtleShhdXRoOiBBdXRoSW50ZXJuYWwpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgICAgaWYgKCFmb3JjZVJlZnJlc2gpIHtcbiAgICAgICAgaWYgKGF1dGgudGVuYW50SWQgPT0gbnVsbCAmJiBhdXRoLl9hZ2VudFJlY2FwdGNoYUNvbmZpZyAhPSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGF1dGguX2FnZW50UmVjYXB0Y2hhQ29uZmlnLnNpdGVLZXk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGF1dGgudGVuYW50SWQgIT0gbnVsbCAmJlxuICAgICAgICAgIGF1dGguX3RlbmFudFJlY2FwdGNoYUNvbmZpZ3NbYXV0aC50ZW5hbnRJZF0gIT09IHVuZGVmaW5lZFxuICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gYXV0aC5fdGVuYW50UmVjYXB0Y2hhQ29uZmlnc1thdXRoLnRlbmFudElkXS5zaXRlS2V5O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxzdHJpbmc+KGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZ2V0UmVjYXB0Y2hhQ29uZmlnKGF1dGgsIHtcbiAgICAgICAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQixcbiAgICAgICAgICB2ZXJzaW9uOiBSZWNhcHRjaGFWZXJzaW9uLkVOVEVSUFJJU0VcbiAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzcG9uc2UucmVjYXB0Y2hhS2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcigncmVjYXB0Y2hhIEVudGVycHJpc2Ugc2l0ZSBrZXkgdW5kZWZpbmVkJykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29uc3QgY29uZmlnID0gbmV3IFJlY2FwdGNoYUNvbmZpZyhyZXNwb25zZSk7XG4gICAgICAgICAgICAgIGlmIChhdXRoLnRlbmFudElkID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhdXRoLl9hZ2VudFJlY2FwdGNoYUNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhdXRoLl90ZW5hbnRSZWNhcHRjaGFDb25maWdzW2F1dGgudGVuYW50SWRdID0gY29uZmlnO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGNvbmZpZy5zaXRlS2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmV0cmlldmVSZWNhcHRjaGFUb2tlbihcbiAgICAgIHNpdGVLZXk6IHN0cmluZyxcbiAgICAgIHJlc29sdmU6ICh2YWx1ZTogc3RyaW5nIHwgUHJvbWlzZUxpa2U8c3RyaW5nPikgPT4gdm9pZCxcbiAgICAgIHJlamVjdDogKHJlYXNvbj86IHVua25vd24pID0+IHZvaWRcbiAgICApOiB2b2lkIHtcbiAgICAgIGNvbnN0IGdyZWNhcHRjaGEgPSB3aW5kb3cuZ3JlY2FwdGNoYTtcbiAgICAgIGlmIChpc0VudGVycHJpc2UoZ3JlY2FwdGNoYSkpIHtcbiAgICAgICAgZ3JlY2FwdGNoYS5lbnRlcnByaXNlLnJlYWR5KCgpID0+IHtcbiAgICAgICAgICBncmVjYXB0Y2hhLmVudGVycHJpc2VcbiAgICAgICAgICAgIC5leGVjdXRlKHNpdGVLZXksIHsgYWN0aW9uIH0pXG4gICAgICAgICAgICAudGhlbih0b2tlbiA9PiB7XG4gICAgICAgICAgICAgIHJlc29sdmUodG9rZW4pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAgIHJlc29sdmUoRkFLRV9UT0tFTik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWplY3QoRXJyb3IoJ05vIHJlQ0FQVENIQSBlbnRlcnByaXNlIHNjcmlwdCBsb2FkZWQuJykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybnMgUHJvbWlzZSBmb3IgYSBtb2NrIHRva2VuIHdoZW4gYXBwVmVyaWZpY2F0aW9uRGlzYWJsZWRGb3JUZXN0aW5nIGlzIHRydWUuXG4gICAgaWYgKHRoaXMuYXV0aC5zZXR0aW5ncy5hcHBWZXJpZmljYXRpb25EaXNhYmxlZEZvclRlc3RpbmcpIHtcbiAgICAgIGNvbnN0IG1vY2tSZWNhcHRjaGEgPSBuZXcgTW9ja0dyZUNBUFRDSEFUb3BMZXZlbCgpO1xuICAgICAgcmV0dXJuIG1vY2tSZWNhcHRjaGEuZXhlY3V0ZSgnc2l0ZUtleScsIHsgYWN0aW9uOiAndmVyaWZ5JyB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICByZXRyaWV2ZVNpdGVLZXkodGhpcy5hdXRoKVxuICAgICAgICAudGhlbihzaXRlS2V5ID0+IHtcbiAgICAgICAgICBpZiAoIWZvcmNlUmVmcmVzaCAmJiBpc0VudGVycHJpc2Uod2luZG93LmdyZWNhcHRjaGEpKSB7XG4gICAgICAgICAgICByZXRyaWV2ZVJlY2FwdGNoYVRva2VuKHNpdGVLZXksIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICByZWplY3QoXG4gICAgICAgICAgICAgICAgbmV3IEVycm9yKCdSZWNhcHRjaGFWZXJpZmllciBpcyBvbmx5IHN1cHBvcnRlZCBpbiBicm93c2VyJylcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHVybCA9IGpzSGVscGVycy5fcmVjYXB0Y2hhRW50ZXJwcmlzZVNjcmlwdFVybCgpO1xuICAgICAgICAgICAgaWYgKHVybC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgdXJsICs9IHNpdGVLZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBqc0hlbHBlcnNcbiAgICAgICAgICAgICAgLl9sb2FkSlModXJsKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0cmlldmVSZWNhcHRjaGFUb2tlbihzaXRlS2V5LCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5qZWN0UmVjYXB0Y2hhRmllbGRzPFQgZXh0ZW5kcyBvYmplY3Q+KFxuICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFQsXG4gIGFjdGlvbjogUmVjYXB0Y2hhQWN0aW9uTmFtZSxcbiAgaXNDYXB0Y2hhUmVzcCA9IGZhbHNlLFxuICBpc0Zha2VUb2tlbiA9IGZhbHNlXG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgdmVyaWZpZXIgPSBuZXcgUmVjYXB0Y2hhRW50ZXJwcmlzZVZlcmlmaWVyKGF1dGgpO1xuICBsZXQgY2FwdGNoYVJlc3BvbnNlO1xuXG4gIGlmIChpc0Zha2VUb2tlbikge1xuICAgIGNhcHRjaGFSZXNwb25zZSA9IEZBS0VfVE9LRU47XG4gIH0gZWxzZSB7XG4gICAgdHJ5IHtcbiAgICAgIGNhcHRjaGFSZXNwb25zZSA9IGF3YWl0IHZlcmlmaWVyLnZlcmlmeShhY3Rpb24pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjYXB0Y2hhUmVzcG9uc2UgPSBhd2FpdCB2ZXJpZmllci52ZXJpZnkoYWN0aW9uLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBuZXdSZXF1ZXN0ID0geyAuLi5yZXF1ZXN0IH07XG4gIGlmIChcbiAgICBhY3Rpb24gPT09IFJlY2FwdGNoYUFjdGlvbk5hbWUuTUZBX1NNU19FTlJPTExNRU5UIHx8XG4gICAgYWN0aW9uID09PSBSZWNhcHRjaGFBY3Rpb25OYW1lLk1GQV9TTVNfU0lHTklOXG4gICkge1xuICAgIGlmICgncGhvbmVFbnJvbGxtZW50SW5mbycgaW4gbmV3UmVxdWVzdCkge1xuICAgICAgY29uc3QgcGhvbmVOdW1iZXIgPSAoXG4gICAgICAgIG5ld1JlcXVlc3QgYXMgdW5rbm93biBhcyBTdGFydFBob25lTWZhRW5yb2xsbWVudFJlcXVlc3RcbiAgICAgICkucGhvbmVFbnJvbGxtZW50SW5mby5waG9uZU51bWJlcjtcbiAgICAgIGNvbnN0IHJlY2FwdGNoYVRva2VuID0gKFxuICAgICAgICBuZXdSZXF1ZXN0IGFzIHVua25vd24gYXMgU3RhcnRQaG9uZU1mYUVucm9sbG1lbnRSZXF1ZXN0XG4gICAgICApLnBob25lRW5yb2xsbWVudEluZm8ucmVjYXB0Y2hhVG9rZW47XG5cbiAgICAgIE9iamVjdC5hc3NpZ24obmV3UmVxdWVzdCwge1xuICAgICAgICAncGhvbmVFbnJvbGxtZW50SW5mbyc6IHtcbiAgICAgICAgICBwaG9uZU51bWJlcixcbiAgICAgICAgICByZWNhcHRjaGFUb2tlbixcbiAgICAgICAgICBjYXB0Y2hhUmVzcG9uc2UsXG4gICAgICAgICAgJ2NsaWVudFR5cGUnOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQixcbiAgICAgICAgICAncmVjYXB0Y2hhVmVyc2lvbic6IFJlY2FwdGNoYVZlcnNpb24uRU5URVJQUklTRVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKCdwaG9uZVNpZ25JbkluZm8nIGluIG5ld1JlcXVlc3QpIHtcbiAgICAgIGNvbnN0IHJlY2FwdGNoYVRva2VuID0gKFxuICAgICAgICBuZXdSZXF1ZXN0IGFzIHVua25vd24gYXMgU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3RcbiAgICAgICkucGhvbmVTaWduSW5JbmZvLnJlY2FwdGNoYVRva2VuO1xuXG4gICAgICBPYmplY3QuYXNzaWduKG5ld1JlcXVlc3QsIHtcbiAgICAgICAgJ3Bob25lU2lnbkluSW5mbyc6IHtcbiAgICAgICAgICByZWNhcHRjaGFUb2tlbixcbiAgICAgICAgICBjYXB0Y2hhUmVzcG9uc2UsXG4gICAgICAgICAgJ2NsaWVudFR5cGUnOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQixcbiAgICAgICAgICAncmVjYXB0Y2hhVmVyc2lvbic6IFJlY2FwdGNoYVZlcnNpb24uRU5URVJQUklTRVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld1JlcXVlc3Q7XG4gIH1cblxuICBpZiAoIWlzQ2FwdGNoYVJlc3ApIHtcbiAgICBPYmplY3QuYXNzaWduKG5ld1JlcXVlc3QsIHsgY2FwdGNoYVJlc3BvbnNlIH0pO1xuICB9IGVsc2Uge1xuICAgIE9iamVjdC5hc3NpZ24obmV3UmVxdWVzdCwgeyAnY2FwdGNoYVJlc3AnOiBjYXB0Y2hhUmVzcG9uc2UgfSk7XG4gIH1cbiAgT2JqZWN0LmFzc2lnbihuZXdSZXF1ZXN0LCB7ICdjbGllbnRUeXBlJzogUmVjYXB0Y2hhQ2xpZW50VHlwZS5XRUIgfSk7XG4gIE9iamVjdC5hc3NpZ24obmV3UmVxdWVzdCwge1xuICAgICdyZWNhcHRjaGFWZXJzaW9uJzogUmVjYXB0Y2hhVmVyc2lvbi5FTlRFUlBSSVNFXG4gIH0pO1xuICByZXR1cm4gbmV3UmVxdWVzdDtcbn1cblxudHlwZSBBY3Rpb25NZXRob2Q8VFJlcXVlc3QsIFRSZXNwb25zZT4gPSAoXG4gIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgcmVxdWVzdDogVFJlcXVlc3RcbikgPT4gUHJvbWlzZTxUUmVzcG9uc2U+O1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmVjYXB0Y2hhRmxvdzxUUmVxdWVzdCBleHRlbmRzIG9iamVjdCwgVFJlc3BvbnNlPihcbiAgYXV0aEluc3RhbmNlOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFRSZXF1ZXN0LFxuICBhY3Rpb25OYW1lOiBSZWNhcHRjaGFBY3Rpb25OYW1lLFxuICBhY3Rpb25NZXRob2Q6IEFjdGlvbk1ldGhvZDxUUmVxdWVzdCwgVFJlc3BvbnNlPixcbiAgcmVjYXB0Y2hhQXV0aFByb3ZpZGVyOiBSZWNhcHRjaGFBdXRoUHJvdmlkZXJcbik6IFByb21pc2U8VFJlc3BvbnNlPiB7XG4gIGlmIChyZWNhcHRjaGFBdXRoUHJvdmlkZXIgPT09IFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUikge1xuICAgIGlmIChcbiAgICAgIGF1dGhJbnN0YW5jZVxuICAgICAgICAuX2dldFJlY2FwdGNoYUNvbmZpZygpXG4gICAgICAgID8uaXNQcm92aWRlckVuYWJsZWQoUmVjYXB0Y2hhQXV0aFByb3ZpZGVyLkVNQUlMX1BBU1NXT1JEX1BST1ZJREVSKVxuICAgICkge1xuICAgICAgY29uc3QgcmVxdWVzdFdpdGhSZWNhcHRjaGEgPSBhd2FpdCBpbmplY3RSZWNhcHRjaGFGaWVsZHMoXG4gICAgICAgIGF1dGhJbnN0YW5jZSxcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgYWN0aW9uTmFtZSxcbiAgICAgICAgYWN0aW9uTmFtZSA9PT0gUmVjYXB0Y2hhQWN0aW9uTmFtZS5HRVRfT09CX0NPREVcbiAgICAgICk7XG4gICAgICByZXR1cm4gYWN0aW9uTWV0aG9kKGF1dGhJbnN0YW5jZSwgcmVxdWVzdFdpdGhSZWNhcHRjaGEpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYWN0aW9uTWV0aG9kKGF1dGhJbnN0YW5jZSwgcmVxdWVzdCkuY2F0Y2goYXN5bmMgZXJyb3IgPT4ge1xuICAgICAgICBpZiAoZXJyb3IuY29kZSA9PT0gYGF1dGgvJHtBdXRoRXJyb3JDb2RlLk1JU1NJTkdfUkVDQVBUQ0hBX1RPS0VOfWApIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGAke2FjdGlvbk5hbWV9IGlzIHByb3RlY3RlZCBieSByZUNBUFRDSEEgRW50ZXJwcmlzZSBmb3IgdGhpcyBwcm9qZWN0LiBBdXRvbWF0aWNhbGx5IHRyaWdnZXJpbmcgdGhlIHJlQ0FQVENIQSBmbG93IGFuZCByZXN0YXJ0aW5nIHRoZSBmbG93LmBcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHJlcXVlc3RXaXRoUmVjYXB0Y2hhID0gYXdhaXQgaW5qZWN0UmVjYXB0Y2hhRmllbGRzKFxuICAgICAgICAgICAgYXV0aEluc3RhbmNlLFxuICAgICAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgICAgIGFjdGlvbk5hbWUsXG4gICAgICAgICAgICBhY3Rpb25OYW1lID09PSBSZWNhcHRjaGFBY3Rpb25OYW1lLkdFVF9PT0JfQ09ERVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIGFjdGlvbk1ldGhvZChhdXRoSW5zdGFuY2UsIHJlcXVlc3RXaXRoUmVjYXB0Y2hhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH0gZWxzZSBpZiAocmVjYXB0Y2hhQXV0aFByb3ZpZGVyID09PSBSZWNhcHRjaGFBdXRoUHJvdmlkZXIuUEhPTkVfUFJPVklERVIpIHtcbiAgICBpZiAoXG4gICAgICBhdXRoSW5zdGFuY2VcbiAgICAgICAgLl9nZXRSZWNhcHRjaGFDb25maWcoKVxuICAgICAgICA/LmlzUHJvdmlkZXJFbmFibGVkKFJlY2FwdGNoYUF1dGhQcm92aWRlci5QSE9ORV9QUk9WSURFUilcbiAgICApIHtcbiAgICAgIGNvbnN0IHJlcXVlc3RXaXRoUmVjYXB0Y2hhID0gYXdhaXQgaW5qZWN0UmVjYXB0Y2hhRmllbGRzKFxuICAgICAgICBhdXRoSW5zdGFuY2UsXG4gICAgICAgIHJlcXVlc3QsXG4gICAgICAgIGFjdGlvbk5hbWVcbiAgICAgICk7XG5cbiAgICAgIHJldHVybiBhY3Rpb25NZXRob2QoYXV0aEluc3RhbmNlLCByZXF1ZXN0V2l0aFJlY2FwdGNoYSkuY2F0Y2goXG4gICAgICAgIGFzeW5jIGVycm9yID0+IHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBhdXRoSW5zdGFuY2VcbiAgICAgICAgICAgICAgLl9nZXRSZWNhcHRjaGFDb25maWcoKVxuICAgICAgICAgICAgICA/LmdldFByb3ZpZGVyRW5mb3JjZW1lbnRTdGF0ZShcbiAgICAgICAgICAgICAgICBSZWNhcHRjaGFBdXRoUHJvdmlkZXIuUEhPTkVfUFJPVklERVJcbiAgICAgICAgICAgICAgKSA9PT0gRW5mb3JjZW1lbnRTdGF0ZS5BVURJVFxuICAgICAgICAgICkge1xuICAgICAgICAgICAgLy8gQVVESVQgbW9kZVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICBlcnJvci5jb2RlID09PSBgYXV0aC8ke0F1dGhFcnJvckNvZGUuTUlTU0lOR19SRUNBUFRDSEFfVE9LRU59YCB8fFxuICAgICAgICAgICAgICBlcnJvci5jb2RlID09PSBgYXV0aC8ke0F1dGhFcnJvckNvZGUuSU5WQUxJRF9BUFBfQ1JFREVOVElBTH1gXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgYEZhaWxlZCB0byB2ZXJpZnkgd2l0aCByZUNBUFRDSEEgRW50ZXJwcmlzZS4gQXV0b21hdGljYWxseSB0cmlnZ2VyaW5nIHRoZSByZUNBUFRDSEEgdjIgZmxvdyB0byBjb21wbGV0ZSB0aGUgJHthY3Rpb25OYW1lfSBmbG93LmBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgLy8gcmVDQVBUQ0hBIEVudGVycHJpc2UgdG9rZW4gaXMgbWlzc2luZyBvciByZUNBUFRDSEEgRW50ZXJwcmlzZSB0b2tlblxuICAgICAgICAgICAgICAvLyBjaGVjayBmYWlscy5cbiAgICAgICAgICAgICAgLy8gRmFsbGJhY2sgdG8gcmVDQVBUQ0hBIHYyIGZsb3cuXG4gICAgICAgICAgICAgIGNvbnN0IHJlcXVlc3RXaXRoUmVjYXB0Y2hhRmllbGRzID0gYXdhaXQgaW5qZWN0UmVjYXB0Y2hhRmllbGRzKFxuICAgICAgICAgICAgICAgIGF1dGhJbnN0YW5jZSxcbiAgICAgICAgICAgICAgICByZXF1ZXN0LFxuICAgICAgICAgICAgICAgIGFjdGlvbk5hbWUsXG4gICAgICAgICAgICAgICAgZmFsc2UsIC8vIGlzQ2FwdGNoYVJlc3BcbiAgICAgICAgICAgICAgICB0cnVlIC8vIGlzRmFrZVRva2VuXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBjYWxsIHRoZSBQaG9uZUFwaUNhbGxlciB0byBmZXRjaCBhbmQgaW5qZWN0IHJlQ0FQVENIQSB2MiB0b2tlbi5cbiAgICAgICAgICAgICAgcmV0dXJuIGFjdGlvbk1ldGhvZChhdXRoSW5zdGFuY2UsIHJlcXVlc3RXaXRoUmVjYXB0Y2hhRmllbGRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gRU5GT1JDRSBtb2RlIG9yIEFVRElUIG1vZGUgd2l0aCBhbnkgb3RoZXIgZXJyb3IuXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRG8gcmVDQVBUQ0hBIHYyIGZsb3cuXG4gICAgICBjb25zdCByZXF1ZXN0V2l0aFJlY2FwdGNoYUZpZWxkcyA9IGF3YWl0IGluamVjdFJlY2FwdGNoYUZpZWxkcyhcbiAgICAgICAgYXV0aEluc3RhbmNlLFxuICAgICAgICByZXF1ZXN0LFxuICAgICAgICBhY3Rpb25OYW1lLFxuICAgICAgICBmYWxzZSwgLy8gaXNDYXB0Y2hhUmVzcFxuICAgICAgICB0cnVlIC8vIGlzRmFrZVRva2VuXG4gICAgICApO1xuXG4gICAgICAvLyBUaGlzIHdpbGwgY2FsbCB0aGUgUGhvbmVBcGlDYWxsZXIgdG8gZmV0Y2ggYW5kIGluamVjdCB2MiB0b2tlbi5cbiAgICAgIHJldHVybiBhY3Rpb25NZXRob2QoYXV0aEluc3RhbmNlLCByZXF1ZXN0V2l0aFJlY2FwdGNoYUZpZWxkcyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIHJlY2FwdGNoYUF1dGhQcm92aWRlciArICcgcHJvdmlkZXIgaXMgbm90IHN1cHBvcnRlZC4nXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX2luaXRpYWxpemVSZWNhcHRjaGFDb25maWcoYXV0aDogQXV0aCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBnZXRSZWNhcHRjaGFDb25maWcoYXV0aEludGVybmFsLCB7XG4gICAgY2xpZW50VHlwZTogUmVjYXB0Y2hhQ2xpZW50VHlwZS5XRUIsXG4gICAgdmVyc2lvbjogUmVjYXB0Y2hhVmVyc2lvbi5FTlRFUlBSSVNFXG4gIH0pO1xuXG4gIGNvbnN0IGNvbmZpZyA9IG5ldyBSZWNhcHRjaGFDb25maWcocmVzcG9uc2UpO1xuICBpZiAoYXV0aEludGVybmFsLnRlbmFudElkID09IG51bGwpIHtcbiAgICBhdXRoSW50ZXJuYWwuX2FnZW50UmVjYXB0Y2hhQ29uZmlnID0gY29uZmlnO1xuICB9IGVsc2Uge1xuICAgIGF1dGhJbnRlcm5hbC5fdGVuYW50UmVjYXB0Y2hhQ29uZmlnc1thdXRoSW50ZXJuYWwudGVuYW50SWRdID0gY29uZmlnO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5pc0FueVByb3ZpZGVyRW5hYmxlZCgpKSB7XG4gICAgY29uc3QgdmVyaWZpZXIgPSBuZXcgUmVjYXB0Y2hhRW50ZXJwcmlzZVZlcmlmaWVyKGF1dGhJbnRlcm5hbCk7XG4gICAgdm9pZCB2ZXJpZmllci52ZXJpZnkoKTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IF9nZXRQcm92aWRlciwgRmlyZWJhc2VBcHAgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IGRlZXBFcXVhbCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEF1dGgsIERlcGVuZGVuY2llcyB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgUGVyc2lzdGVuY2VJbnRlcm5hbCB9IGZyb20gJy4uL3BlcnNpc3RlbmNlJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgX2dldEluc3RhbmNlIH0gZnJvbSAnLi4vdXRpbC9pbnN0YW50aWF0b3InO1xuaW1wb3J0IHsgQXV0aEltcGwgfSBmcm9tICcuL2F1dGhfaW1wbCc7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4ge0BsaW5rIEF1dGh9IGluc3RhbmNlIHdpdGggZmluZS1ncmFpbmVkIGNvbnRyb2wgb3ZlclxuICoge0BsaW5rIERlcGVuZGVuY2llc30uXG4gKlxuICogQHJlbWFya3NcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGFsbG93cyBtb3JlIGNvbnRyb2wgb3ZlciB0aGUge0BsaW5rIEF1dGh9IGluc3RhbmNlIHRoYW5cbiAqIHtAbGluayBnZXRBdXRofS4gYGdldEF1dGhgIHVzZXMgcGxhdGZvcm0tc3BlY2lmaWMgZGVmYXVsdHMgdG8gc3VwcGx5XG4gKiB0aGUge0BsaW5rIERlcGVuZGVuY2llc30uIEluIGdlbmVyYWwsIGBnZXRBdXRoYCBpcyB0aGUgZWFzaWVzdCB3YXkgdG9cbiAqIGluaXRpYWxpemUgQXV0aCBhbmQgd29ya3MgZm9yIG1vc3QgdXNlIGNhc2VzLiBVc2UgYGluaXRpYWxpemVBdXRoYCBpZiB5b3VcbiAqIG5lZWQgY29udHJvbCBvdmVyIHdoaWNoIHBlcnNpc3RlbmNlIGxheWVyIGlzIHVzZWQsIG9yIHRvIG1pbmltaXplIGJ1bmRsZVxuICogc2l6ZSBpZiB5b3UncmUgbm90IHVzaW5nIGVpdGhlciBgc2lnbkluV2l0aFBvcHVwYCBvciBgc2lnbkluV2l0aFJlZGlyZWN0YC5cbiAqXG4gKiBGb3IgZXhhbXBsZSwgaWYgeW91ciBhcHAgb25seSB1c2VzIGFub255bW91cyBhY2NvdW50cyBhbmQgeW91IG9ubHkgd2FudFxuICogYWNjb3VudHMgc2F2ZWQgZm9yIHRoZSBjdXJyZW50IHNlc3Npb24sIGluaXRpYWxpemUgYEF1dGhgIHdpdGg6XG4gKlxuICogYGBganNcbiAqIGNvbnN0IGF1dGggPSBpbml0aWFsaXplQXV0aChhcHAsIHtcbiAqICAgcGVyc2lzdGVuY2U6IGJyb3dzZXJTZXNzaW9uUGVyc2lzdGVuY2UsXG4gKiAgIHBvcHVwUmVkaXJlY3RSZXNvbHZlcjogdW5kZWZpbmVkLFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplQXV0aChhcHA6IEZpcmViYXNlQXBwLCBkZXBzPzogRGVwZW5kZW5jaWVzKTogQXV0aCB7XG4gIGNvbnN0IHByb3ZpZGVyID0gX2dldFByb3ZpZGVyKGFwcCwgJ2F1dGgnKTtcblxuICBpZiAocHJvdmlkZXIuaXNJbml0aWFsaXplZCgpKSB7XG4gICAgY29uc3QgYXV0aCA9IHByb3ZpZGVyLmdldEltbWVkaWF0ZSgpIGFzIEF1dGhJbXBsO1xuICAgIGNvbnN0IGluaXRpYWxPcHRpb25zID0gcHJvdmlkZXIuZ2V0T3B0aW9ucygpIGFzIERlcGVuZGVuY2llcztcbiAgICBpZiAoZGVlcEVxdWFsKGluaXRpYWxPcHRpb25zLCBkZXBzID8/IHt9KSkge1xuICAgICAgcmV0dXJuIGF1dGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuQUxSRUFEWV9JTklUSUFMSVpFRCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgYXV0aCA9IHByb3ZpZGVyLmluaXRpYWxpemUoeyBvcHRpb25zOiBkZXBzIH0pIGFzIEF1dGhJbXBsO1xuXG4gIHJldHVybiBhdXRoO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX2luaXRpYWxpemVBdXRoSW5zdGFuY2UoXG4gIGF1dGg6IEF1dGhJbXBsLFxuICBkZXBzPzogRGVwZW5kZW5jaWVzXG4pOiB2b2lkIHtcbiAgY29uc3QgcGVyc2lzdGVuY2UgPSBkZXBzPy5wZXJzaXN0ZW5jZSB8fCBbXTtcbiAgY29uc3QgaGllcmFyY2h5ID0gKFxuICAgIEFycmF5LmlzQXJyYXkocGVyc2lzdGVuY2UpID8gcGVyc2lzdGVuY2UgOiBbcGVyc2lzdGVuY2VdXG4gICkubWFwPFBlcnNpc3RlbmNlSW50ZXJuYWw+KF9nZXRJbnN0YW5jZSk7XG4gIGlmIChkZXBzPy5lcnJvck1hcCkge1xuICAgIGF1dGguX3VwZGF0ZUVycm9yTWFwKGRlcHMuZXJyb3JNYXApO1xuICB9XG5cbiAgLy8gVGhpcyBwcm9taXNlIGlzIGludGVuZGVkIHRvIGZsb2F0OyBhdXRoIGluaXRpYWxpemF0aW9uIGhhcHBlbnMgaW4gdGhlXG4gIC8vIGJhY2tncm91bmQsIG1lYW53aGlsZSB0aGUgYXV0aCBvYmplY3QgbWF5IGJlIHVzZWQgYnkgdGhlIGFwcC5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1mbG9hdGluZy1wcm9taXNlc1xuICBhdXRoLl9pbml0aWFsaXplV2l0aFBlcnNpc3RlbmNlKGhpZXJhcmNoeSwgZGVwcz8ucG9wdXBSZWRpcmVjdFJlc29sdmVyKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfY2FzdEF1dGggfSBmcm9tICcuL2F1dGhfaW1wbCc7XG5pbXBvcnQge1xuICBkZWVwRXF1YWwsXG4gIGlzQ2xvdWRXb3Jrc3RhdGlvbixcbiAgcGluZ1NlcnZlcixcbiAgdXBkYXRlRW11bGF0b3JCYW5uZXJcbn0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vKipcbiAqIENoYW5nZXMgdGhlIHtAbGluayBBdXRofSBpbnN0YW5jZSB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBGaXJlYmFzZSBBdXRoIEVtdWxhdG9yLCBpbnN0ZWFkIG9mIHByb2R1Y3Rpb25cbiAqIEZpcmViYXNlIEF1dGggc2VydmljZXMuXG4gKlxuICogQHJlbWFya3NcbiAqIFRoaXMgbXVzdCBiZSBjYWxsZWQgc3luY2hyb25vdXNseSBpbW1lZGlhdGVseSBmb2xsb3dpbmcgdGhlIGZpcnN0IGNhbGwgdG9cbiAqIHtAbGluayBpbml0aWFsaXplQXV0aH0uICBEbyBub3QgdXNlIHdpdGggcHJvZHVjdGlvbiBjcmVkZW50aWFscyBhcyBlbXVsYXRvclxuICogdHJhZmZpYyBpcyBub3QgZW5jcnlwdGVkLlxuICpcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogY29ubmVjdEF1dGhFbXVsYXRvcihhdXRoLCAnaHR0cDovLzEyNy4wLjAuMTo5MDk5JywgeyBkaXNhYmxlV2FybmluZ3M6IHRydWUgfSk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCBhdCB3aGljaCB0aGUgZW11bGF0b3IgaXMgcnVubmluZyAoZWcsICdodHRwOi8vbG9jYWxob3N0OjkwOTknKS5cbiAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9uYWwuIGBvcHRpb25zLmRpc2FibGVXYXJuaW5nc2AgZGVmYXVsdHMgdG8gYGZhbHNlYC4gU2V0IGl0IHRvXG4gKiBgdHJ1ZWAgdG8gZGlzYWJsZSB0aGUgd2FybmluZyBiYW5uZXIgYXR0YWNoZWQgdG8gdGhlIERPTS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25uZWN0QXV0aEVtdWxhdG9yKFxuICBhdXRoOiBBdXRoLFxuICB1cmw6IHN0cmluZyxcbiAgb3B0aW9ucz86IHsgZGlzYWJsZVdhcm5pbmdzOiBib29sZWFuIH1cbik6IHZvaWQge1xuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG4gIF9hc3NlcnQoXG4gICAgL15odHRwcz86XFwvXFwvLy50ZXN0KHVybCksXG4gICAgYXV0aEludGVybmFsLFxuICAgIEF1dGhFcnJvckNvZGUuSU5WQUxJRF9FTVVMQVRPUl9TQ0hFTUVcbiAgKTtcblxuICBjb25zdCBkaXNhYmxlV2FybmluZ3MgPSAhIW9wdGlvbnM/LmRpc2FibGVXYXJuaW5ncztcblxuICBjb25zdCBwcm90b2NvbCA9IGV4dHJhY3RQcm90b2NvbCh1cmwpO1xuICBjb25zdCB7IGhvc3QsIHBvcnQgfSA9IGV4dHJhY3RIb3N0QW5kUG9ydCh1cmwpO1xuICBjb25zdCBwb3J0U3RyID0gcG9ydCA9PT0gbnVsbCA/ICcnIDogYDoke3BvcnR9YDtcblxuICAvLyBBbHdheXMgcmVwbGFjZSBwYXRoIHdpdGggXCIvXCIgKGV2ZW4gaWYgaW5wdXQgdXJsIGhhZCBubyBwYXRoIGF0IGFsbCwgb3IgaGFkIGEgZGlmZmVyZW50IG9uZSkuXG4gIGNvbnN0IGVtdWxhdG9yID0geyB1cmw6IGAke3Byb3RvY29sfS8vJHtob3N0fSR7cG9ydFN0cn0vYCB9O1xuICBjb25zdCBlbXVsYXRvckNvbmZpZyA9IE9iamVjdC5mcmVlemUoe1xuICAgIGhvc3QsXG4gICAgcG9ydCxcbiAgICBwcm90b2NvbDogcHJvdG9jb2wucmVwbGFjZSgnOicsICcnKSxcbiAgICBvcHRpb25zOiBPYmplY3QuZnJlZXplKHsgZGlzYWJsZVdhcm5pbmdzIH0pXG4gIH0pO1xuXG4gIC8vIFRoZXJlIGFyZSBhIGZldyBzY2VuYXJpb3MgdG8gZ3VhcmQgYWdhaW5zdCBpZiB0aGUgQXV0aCBpbnN0YW5jZSBoYXMgYWxyZWFkeSBzdGFydGVkOlxuICBpZiAoIWF1dGhJbnRlcm5hbC5fY2FuSW5pdEVtdWxhdG9yKSB7XG4gICAgLy8gQXBwbGljYXRpb25zIG1heSBub3QgaW5pdGlhbGl6ZSB0aGUgZW11bGF0b3IgZm9yIHRoZSBmaXJzdCB0aW1lIGlmIEF1dGggaGFzIGFscmVhZHkgc3RhcnRlZFxuICAgIC8vIHRvIG1ha2UgbmV0d29yayByZXF1ZXN0cy5cbiAgICBfYXNzZXJ0KFxuICAgICAgYXV0aEludGVybmFsLmNvbmZpZy5lbXVsYXRvciAmJiBhdXRoSW50ZXJuYWwuZW11bGF0b3JDb25maWcsXG4gICAgICBhdXRoSW50ZXJuYWwsXG4gICAgICBBdXRoRXJyb3JDb2RlLkVNVUxBVE9SX0NPTkZJR19GQUlMRURcbiAgICApO1xuXG4gICAgLy8gQXBwbGljYXRpb25zIG1heSBub3QgYWx0ZXIgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIGVtdWxhdG9yIChha2EgcGFzcyBhIGRpZmZlcmVudCBjb25maWcpXG4gICAgLy8gb25jZSBBdXRoIGhhcyBzdGFydGVkIHRvIG1ha2UgbmV0d29yayByZXF1ZXN0cy5cbiAgICBfYXNzZXJ0KFxuICAgICAgZGVlcEVxdWFsKGVtdWxhdG9yLCBhdXRoSW50ZXJuYWwuY29uZmlnLmVtdWxhdG9yKSAmJlxuICAgICAgICBkZWVwRXF1YWwoZW11bGF0b3JDb25maWcsIGF1dGhJbnRlcm5hbC5lbXVsYXRvckNvbmZpZyksXG4gICAgICBhdXRoSW50ZXJuYWwsXG4gICAgICBBdXRoRXJyb3JDb2RlLkVNVUxBVE9SX0NPTkZJR19GQUlMRURcbiAgICApO1xuXG4gICAgLy8gSXQncyB2YWxpZCwgaG93ZXZlciwgdG8gaW52b2tlIGNvbm5lY3RBdXRoRW11bGF0b3IoKSBhZnRlciBBdXRoIGhhcyBzdGFydGVkIG1ha2luZ1xuICAgIC8vIGNvbm5lY3Rpb25zLCBzbyBsb25nIGFzIHRoZSBjb25maWcgbWF0Y2hlcyB0aGUgZXhpc3RpbmcgY29uZmlnLiBUaGlzIHJlc3VsdHMgaW4gYSBuby1vcC5cbiAgICByZXR1cm47XG4gIH1cblxuICBhdXRoSW50ZXJuYWwuY29uZmlnLmVtdWxhdG9yID0gZW11bGF0b3I7XG4gIGF1dGhJbnRlcm5hbC5lbXVsYXRvckNvbmZpZyA9IGVtdWxhdG9yQ29uZmlnO1xuICBhdXRoSW50ZXJuYWwuc2V0dGluZ3MuYXBwVmVyaWZpY2F0aW9uRGlzYWJsZWRGb3JUZXN0aW5nID0gdHJ1ZTtcblxuICAvLyBXb3JrYXJvdW5kIHRvIGdldCBjb29raWVzIGluIEZpcmViYXNlIFN0dWRpb1xuICBpZiAoaXNDbG91ZFdvcmtzdGF0aW9uKGhvc3QpKSB7XG4gICAgdm9pZCBwaW5nU2VydmVyKGAke3Byb3RvY29sfS8vJHtob3N0fSR7cG9ydFN0cn1gKTtcbiAgICB1cGRhdGVFbXVsYXRvckJhbm5lcignQXV0aCcsIHRydWUpO1xuICB9IGVsc2UgaWYgKCFkaXNhYmxlV2FybmluZ3MpIHtcbiAgICBlbWl0RW11bGF0b3JXYXJuaW5nKCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZXh0cmFjdFByb3RvY29sKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcHJvdG9jb2xFbmQgPSB1cmwuaW5kZXhPZignOicpO1xuICByZXR1cm4gcHJvdG9jb2xFbmQgPCAwID8gJycgOiB1cmwuc3Vic3RyKDAsIHByb3RvY29sRW5kICsgMSk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RIb3N0QW5kUG9ydCh1cmw6IHN0cmluZyk6IHtcbiAgaG9zdDogc3RyaW5nO1xuICBwb3J0OiBudW1iZXIgfCBudWxsO1xufSB7XG4gIGNvbnN0IHByb3RvY29sID0gZXh0cmFjdFByb3RvY29sKHVybCk7XG4gIGNvbnN0IGF1dGhvcml0eSA9IC8oXFwvXFwvKT8oW14/Iy9dKykvLmV4ZWModXJsLnN1YnN0cihwcm90b2NvbC5sZW5ndGgpKTsgLy8gQmV0d2VlbiAvLyBhbmQgLywgPyBvciAjLlxuICBpZiAoIWF1dGhvcml0eSkge1xuICAgIHJldHVybiB7IGhvc3Q6ICcnLCBwb3J0OiBudWxsIH07XG4gIH1cbiAgY29uc3QgaG9zdEFuZFBvcnQgPSBhdXRob3JpdHlbMl0uc3BsaXQoJ0AnKS5wb3AoKSB8fCAnJzsgLy8gU3RyaXAgb3V0IFwidXNlcm5hbWU6cGFzc3dvcmRAXCIuXG4gIGNvbnN0IGJyYWNrZXRlZElQdjYgPSAvXihcXFtbXlxcXV0rXFxdKSg6fCQpLy5leGVjKGhvc3RBbmRQb3J0KTtcbiAgaWYgKGJyYWNrZXRlZElQdjYpIHtcbiAgICBjb25zdCBob3N0ID0gYnJhY2tldGVkSVB2NlsxXTtcbiAgICByZXR1cm4geyBob3N0LCBwb3J0OiBwYXJzZVBvcnQoaG9zdEFuZFBvcnQuc3Vic3RyKGhvc3QubGVuZ3RoICsgMSkpIH07XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgW2hvc3QsIHBvcnRdID0gaG9zdEFuZFBvcnQuc3BsaXQoJzonKTtcbiAgICByZXR1cm4geyBob3N0LCBwb3J0OiBwYXJzZVBvcnQocG9ydCkgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVBvcnQocG9ydFN0cjogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gIGlmICghcG9ydFN0cikge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHBvcnQgPSBOdW1iZXIocG9ydFN0cik7XG4gIGlmIChpc05hTihwb3J0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiBwb3J0O1xufVxuXG5mdW5jdGlvbiBlbWl0RW11bGF0b3JXYXJuaW5nKCk6IHZvaWQge1xuICBmdW5jdGlvbiBhdHRhY2hCYW5uZXIoKTogdm9pZCB7XG4gICAgY29uc3QgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwJyk7XG4gICAgY29uc3Qgc3R5ID0gZWwuc3R5bGU7XG4gICAgZWwuaW5uZXJUZXh0ID1cbiAgICAgICdSdW5uaW5nIGluIGVtdWxhdG9yIG1vZGUuIERvIG5vdCB1c2Ugd2l0aCBwcm9kdWN0aW9uIGNyZWRlbnRpYWxzLic7XG4gICAgc3R5LnBvc2l0aW9uID0gJ2ZpeGVkJztcbiAgICBzdHkud2lkdGggPSAnMTAwJSc7XG4gICAgc3R5LmJhY2tncm91bmRDb2xvciA9ICcjZmZmZmZmJztcbiAgICBzdHkuYm9yZGVyID0gJy4xZW0gc29saWQgIzAwMDAwMCc7XG4gICAgc3R5LmNvbG9yID0gJyNiNTAwMDAnO1xuICAgIHN0eS5ib3R0b20gPSAnMHB4JztcbiAgICBzdHkubGVmdCA9ICcwcHgnO1xuICAgIHN0eS5tYXJnaW4gPSAnMHB4JztcbiAgICBzdHkuekluZGV4ID0gJzEwMDAwJztcbiAgICBzdHkudGV4dEFsaWduID0gJ2NlbnRlcic7XG4gICAgZWwuY2xhc3NMaXN0LmFkZCgnZmlyZWJhc2UtZW11bGF0b3Itd2FybmluZycpO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZWwpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY29uc29sZS5pbmZvID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29uc29sZS5pbmZvKFxuICAgICAgJ1dBUk5JTkc6IFlvdSBhcmUgdXNpbmcgdGhlIEF1dGggRW11bGF0b3IsJyArXG4gICAgICAgICcgd2hpY2ggaXMgaW50ZW5kZWQgZm9yIGxvY2FsIHRlc3Rpbmcgb25seS4gIERvIG5vdCB1c2Ugd2l0aCcgK1xuICAgICAgICAnIHByb2R1Y3Rpb24gY3JlZGVudGlhbHMuJ1xuICAgICk7XG4gIH1cbiAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGF0dGFjaEJhbm5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF0dGFjaEJhbm5lcigpO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgZGVidWdGYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIEludGVyZmFjZSB0aGF0IHJlcHJlc2VudHMgdGhlIGNyZWRlbnRpYWxzIHJldHVybmVkIGJ5IGFuIHtAbGluayBBdXRoUHJvdmlkZXJ9LlxuICpcbiAqIEByZW1hcmtzXG4gKiBJbXBsZW1lbnRhdGlvbnMgc3BlY2lmeSB0aGUgZGV0YWlscyBhYm91dCBlYWNoIGF1dGggcHJvdmlkZXIncyBjcmVkZW50aWFsIHJlcXVpcmVtZW50cy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoQ3JlZGVudGlhbCB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIC8qKlxuICAgICAqIFRoZSBhdXRoZW50aWNhdGlvbiBwcm92aWRlciBJRCBmb3IgdGhlIGNyZWRlbnRpYWwuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIEZvciBleGFtcGxlLCAnZmFjZWJvb2suY29tJywgb3IgJ2dvb2dsZS5jb20nLlxuICAgICAqL1xuICAgIHJlYWRvbmx5IHByb3ZpZGVySWQ6IHN0cmluZyxcbiAgICAvKipcbiAgICAgKiBUaGUgYXV0aGVudGljYXRpb24gc2lnbiBpbiBtZXRob2QgZm9yIHRoZSBjcmVkZW50aWFsLlxuICAgICAqXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBGb3IgZXhhbXBsZSwge0BsaW5rIFNpZ25Jbk1ldGhvZH0uRU1BSUxfUEFTU1dPUkQsIG9yXG4gICAgICoge0BsaW5rIFNpZ25Jbk1ldGhvZH0uRU1BSUxfTElOSy4gVGhpcyBjb3JyZXNwb25kcyB0byB0aGUgc2lnbi1pbiBtZXRob2RcbiAgICAgKiBpZGVudGlmaWVyIGFzIHJldHVybmVkIGluIHtAbGluayBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbH0uXG4gICAgICovXG4gICAgcmVhZG9ubHkgc2lnbkluTWV0aG9kOiBzdHJpbmdcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgSlNPTi1zZXJpYWxpemFibGUgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvYmplY3QuXG4gICAqXG4gICAqIEByZXR1cm5zIGEgSlNPTi1zZXJpYWxpemFibGUgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvYmplY3QuXG4gICAqL1xuICB0b0pTT04oKTogb2JqZWN0IHtcbiAgICByZXR1cm4gZGVidWdGYWlsKCdub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX2dldElkVG9rZW5SZXNwb25zZShfYXV0aDogQXV0aEludGVybmFsKTogUHJvbWlzZTxQaG9uZU9yT2F1dGhUb2tlblJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIGRlYnVnRmFpbCgnbm90IGltcGxlbWVudGVkJyk7XG4gIH1cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfbGlua1RvSWRUb2tlbihcbiAgICBfYXV0aDogQXV0aEludGVybmFsLFxuICAgIF9pZFRva2VuOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICByZXR1cm4gZGVidWdGYWlsKCdub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuICAvKiogQGludGVybmFsICovXG4gIF9nZXRSZWF1dGhlbnRpY2F0aW9uUmVzb2x2ZXIoX2F1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIGRlYnVnRmFpbCgnbm90IGltcGxlbWVudGVkJyk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBY3Rpb25Db2RlT3BlcmF0aW9uLCBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHtcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeSxcbiAgX3BlcmZvcm1BcGlSZXF1ZXN0XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IE1mYUVucm9sbG1lbnQgfSBmcm9tICcuL21mYSc7XG5pbXBvcnQgeyBTaWduVXBSZXF1ZXN0LCBTaWduVXBSZXNwb25zZSB9IGZyb20gJy4uL2F1dGhlbnRpY2F0aW9uL3NpZ25fdXAnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc2V0UGFzc3dvcmRSZXF1ZXN0IHtcbiAgb29iQ29kZTogc3RyaW5nO1xuICBuZXdQYXNzd29yZD86IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzZXRQYXNzd29yZFJlc3BvbnNlIHtcbiAgZW1haWw6IHN0cmluZztcbiAgbmV3RW1haWw/OiBzdHJpbmc7XG4gIHJlcXVlc3RUeXBlPzogQWN0aW9uQ29kZU9wZXJhdGlvbjtcbiAgbWZhSW5mbz86IE1mYUVucm9sbG1lbnQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNldFBhc3N3b3JkKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBSZXNldFBhc3N3b3JkUmVxdWVzdFxuKTogUHJvbWlzZTxSZXNldFBhc3N3b3JkUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxSZXNldFBhc3N3b3JkUmVxdWVzdCwgUmVzZXRQYXNzd29yZFJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5SRVNFVF9QQVNTV09SRCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHJldHVyblNlY3VyZVRva2VuPzogYm9vbGVhbjtcbiAgZW1haWw/OiBzdHJpbmc7XG4gIHBhc3N3b3JkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZUVtYWlsUGFzc3dvcmRSZXNwb25zZSBleHRlbmRzIElkVG9rZW5SZXNwb25zZSB7fVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlRW1haWxQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3Rcbik6IFByb21pc2U8VXBkYXRlRW1haWxQYXNzd29yZFJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3QsXG4gICAgVXBkYXRlRW1haWxQYXNzd29yZFJlc3BvbnNlXG4gID4oYXV0aCwgSHR0cE1ldGhvZC5QT1NULCBFbmRwb2ludC5TRVRfQUNDT1VOVF9JTkZPLCByZXF1ZXN0KTtcbn1cblxuLy8gVXNlZCBmb3IgbGlua2luZyBhbiBlbWFpbC9wYXNzd29yZCBhY2NvdW50IHRvIGFuIGV4aXN0aW5nIGlkVG9rZW4uIFVzZXMgdGhlIHNhbWUgcmVxdWVzdC9yZXNwb25zZVxuLy8gZm9ybWF0IGFzIHVwZGF0ZUVtYWlsUGFzc3dvcmQuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlua0VtYWlsUGFzc3dvcmQoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25VcFJlcXVlc3Rcbik6IFByb21pc2U8U2lnblVwUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxTaWduVXBSZXF1ZXN0LCBTaWduVXBSZXNwb25zZT4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9VUCxcbiAgICByZXF1ZXN0XG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbHlBY3Rpb25Db2RlUmVxdWVzdCB7XG4gIG9vYkNvZGU6IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbHlBY3Rpb25Db2RlUmVzcG9uc2Uge31cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFwcGx5QWN0aW9uQ29kZShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogQXBwbHlBY3Rpb25Db2RlUmVxdWVzdFxuKTogUHJvbWlzZTxBcHBseUFjdGlvbkNvZGVSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PEFwcGx5QWN0aW9uQ29kZVJlcXVlc3QsIEFwcGx5QWN0aW9uQ29kZVJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TRVRfQUNDT1VOVF9JTkZPLFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEFjdGlvbkNvZGVPcGVyYXRpb24sIEF1dGggfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQge1xuICBFbmRwb2ludCxcbiAgSHR0cE1ldGhvZCxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhVmVyc2lvbixcbiAgX2FkZFRpZElmTmVjZXNzYXJ5LFxuICBfcGVyZm9ybUFwaVJlcXVlc3QsXG4gIF9wZXJmb3JtU2lnbkluUmVxdWVzdFxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJZFRva2VuLCBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aFBhc3N3b3JkUmVxdWVzdCB7XG4gIHJldHVyblNlY3VyZVRva2VuPzogYm9vbGVhbjtcbiAgZW1haWw6IHN0cmluZztcbiAgcGFzc3dvcmQ6IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG4gIGNhcHRjaGFSZXNwb25zZT86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhQYXNzd29yZFJlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHtcbiAgZW1haWw6IHN0cmluZztcbiAgZGlzcGxheU5hbWU6IHN0cmluZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbldpdGhQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2lnbkluV2l0aFBhc3N3b3JkUmVxdWVzdFxuKTogUHJvbWlzZTxTaWduSW5XaXRoUGFzc3dvcmRSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFxuICAgIFNpZ25JbldpdGhQYXNzd29yZFJlcXVlc3QsXG4gICAgU2lnbkluV2l0aFBhc3N3b3JkUmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfUEFTU1dPUkQsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0T29iQ29kZVJlcXVlc3Qge1xuICBlbWFpbD86IHN0cmluZzsgLy8gRXZlcnl0aGluZyBleGNlcHQgVkVSSUZZX0FORF9DSEFOR0VfRU1BSUxcbiAgY29udGludWVVcmw/OiBzdHJpbmc7XG4gIGlPU0J1bmRsZUlkPzogc3RyaW5nO1xuICBpb3NBcHBTdG9yZUlkPzogc3RyaW5nO1xuICBhbmRyb2lkUGFja2FnZU5hbWU/OiBzdHJpbmc7XG4gIGFuZHJvaWRJbnN0YWxsQXBwPzogYm9vbGVhbjtcbiAgYW5kcm9pZE1pbmltdW1WZXJzaW9uQ29kZT86IHN0cmluZztcbiAgY2FuSGFuZGxlQ29kZUluQXBwPzogYm9vbGVhbjtcbiAgZHluYW1pY0xpbmtEb21haW4/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICB0YXJnZXRQcm9qZWN0aWQ/OiBzdHJpbmc7XG4gIGxpbmtEb21haW4/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmVyaWZ5RW1haWxSZXF1ZXN0IGV4dGVuZHMgR2V0T29iQ29kZVJlcXVlc3Qge1xuICByZXF1ZXN0VHlwZTogQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfRU1BSUw7XG4gIGlkVG9rZW46IElkVG9rZW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRSZXNldFJlcXVlc3QgZXh0ZW5kcyBHZXRPb2JDb2RlUmVxdWVzdCB7XG4gIHJlcXVlc3RUeXBlOiBBY3Rpb25Db2RlT3BlcmF0aW9uLlBBU1NXT1JEX1JFU0VUO1xuICBlbWFpbDogc3RyaW5nO1xuICBjYXB0Y2hhUmVzcD86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVtYWlsU2lnbkluUmVxdWVzdCBleHRlbmRzIEdldE9vYkNvZGVSZXF1ZXN0IHtcbiAgcmVxdWVzdFR5cGU6IEFjdGlvbkNvZGVPcGVyYXRpb24uRU1BSUxfU0lHTklOO1xuICBlbWFpbDogc3RyaW5nO1xuICBjYXB0Y2hhUmVzcD86IHN0cmluZztcbiAgY2xpZW50VHlwZT86IFJlY2FwdGNoYUNsaWVudFR5cGU7XG4gIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZlcmlmeUFuZENoYW5nZUVtYWlsUmVxdWVzdCBleHRlbmRzIEdldE9vYkNvZGVSZXF1ZXN0IHtcbiAgcmVxdWVzdFR5cGU6IEFjdGlvbkNvZGVPcGVyYXRpb24uVkVSSUZZX0FORF9DSEFOR0VfRU1BSUw7XG4gIGlkVG9rZW46IElkVG9rZW47XG4gIG5ld0VtYWlsOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBHZXRPb2JDb2RlUmVzcG9uc2Uge1xuICBlbWFpbDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZlcmlmeUVtYWlsUmVzcG9uc2UgZXh0ZW5kcyBHZXRPb2JDb2RlUmVzcG9uc2Uge31cbmV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRSZXNldFJlc3BvbnNlIGV4dGVuZHMgR2V0T29iQ29kZVJlc3BvbnNlIHt9XG5leHBvcnQgaW50ZXJmYWNlIEVtYWlsU2lnbkluUmVzcG9uc2UgZXh0ZW5kcyBHZXRPb2JDb2RlUmVzcG9uc2Uge31cbmV4cG9ydCBpbnRlcmZhY2UgVmVyaWZ5QW5kQ2hhbmdlRW1haWxSZXNwb25zZSBleHRlbmRzIEdldE9vYkNvZGVSZXF1ZXN0IHt9XG5cbmFzeW5jIGZ1bmN0aW9uIHNlbmRPb2JDb2RlKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBHZXRPb2JDb2RlUmVxdWVzdFxuKTogUHJvbWlzZTxHZXRPb2JDb2RlUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxHZXRPb2JDb2RlUmVxdWVzdCwgR2V0T29iQ29kZVJlc3BvbnNlPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TRU5EX09PQl9DT0RFLFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZEVtYWlsVmVyaWZpY2F0aW9uKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBWZXJpZnlFbWFpbFJlcXVlc3Rcbik6IFByb21pc2U8VmVyaWZ5RW1haWxSZXNwb25zZT4ge1xuICByZXR1cm4gc2VuZE9vYkNvZGUoYXV0aCwgcmVxdWVzdCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kUGFzc3dvcmRSZXNldEVtYWlsKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBQYXNzd29yZFJlc2V0UmVxdWVzdFxuKTogUHJvbWlzZTxQYXNzd29yZFJlc2V0UmVzcG9uc2U+IHtcbiAgcmV0dXJuIHNlbmRPb2JDb2RlKGF1dGgsIHJlcXVlc3QpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZFNpZ25JbkxpbmtUb0VtYWlsKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBFbWFpbFNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8RW1haWxTaWduSW5SZXNwb25zZT4ge1xuICByZXR1cm4gc2VuZE9vYkNvZGUoYXV0aCwgcmVxdWVzdCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlBbmRDaGFuZ2VFbWFpbChcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogVmVyaWZ5QW5kQ2hhbmdlRW1haWxSZXF1ZXN0XG4pOiBQcm9taXNlPFZlcmlmeUFuZENoYW5nZUVtYWlsUmVzcG9uc2U+IHtcbiAgcmV0dXJuIHNlbmRPb2JDb2RlKGF1dGgsIHJlcXVlc3QpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIF9wZXJmb3JtU2lnbkluUmVxdWVzdCxcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeVxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTaWduSW5XaXRoRW1haWxMaW5rUmVxdWVzdCB7XG4gIGVtYWlsOiBzdHJpbmc7XG4gIG9vYkNvZGU6IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aEVtYWlsTGlua1Jlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHtcbiAgZW1haWw6IHN0cmluZztcbiAgaXNOZXdVc2VyOiBib29sZWFuO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aEVtYWlsTGluayhcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2lnbkluV2l0aEVtYWlsTGlua1JlcXVlc3Rcbik6IFByb21pc2U8U2lnbkluV2l0aEVtYWlsTGlua1Jlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybVNpZ25JblJlcXVlc3Q8XG4gICAgU2lnbkluV2l0aEVtYWlsTGlua1JlcXVlc3QsXG4gICAgU2lnbkluV2l0aEVtYWlsTGlua1Jlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9JTl9XSVRIX0VNQUlMX0xJTkssXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aEVtYWlsTGlua0ZvckxpbmtpbmdSZXF1ZXN0XG4gIGV4dGVuZHMgU2lnbkluV2l0aEVtYWlsTGlua1JlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduSW5XaXRoRW1haWxMaW5rRm9yTGlua2luZyhcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2lnbkluV2l0aEVtYWlsTGlua0ZvckxpbmtpbmdSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhFbWFpbExpbmtSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFxuICAgIFNpZ25JbldpdGhFbWFpbExpbmtGb3JMaW5raW5nUmVxdWVzdCxcbiAgICBTaWduSW5XaXRoRW1haWxMaW5rUmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TSUdOX0lOX1dJVEhfRU1BSUxfTElOSyxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBQcm92aWRlcklkLCBTaWduSW5NZXRob2QgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5cbmltcG9ydCB7IGxpbmtFbWFpbFBhc3N3b3JkIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9lbWFpbF9hbmRfcGFzc3dvcmQnO1xuaW1wb3J0IHtcbiAgc2lnbkluV2l0aFBhc3N3b3JkLFxuICBTaWduSW5XaXRoUGFzc3dvcmRSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9lbWFpbF9hbmRfcGFzc3dvcmQnO1xuaW1wb3J0IHtcbiAgc2lnbkluV2l0aEVtYWlsTGluayxcbiAgc2lnbkluV2l0aEVtYWlsTGlua0Zvckxpbmtpbmdcbn0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2xpbmsnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2F1dGhfY3JlZGVudGlhbCc7XG5pbXBvcnQgeyBoYW5kbGVSZWNhcHRjaGFGbG93IH0gZnJvbSAnLi4vLi4vcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXInO1xuaW1wb3J0IHtcbiAgUmVjYXB0Y2hhQWN0aW9uTmFtZSxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyXG59IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQgeyBTaWduVXBSZXF1ZXN0IH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL3NpZ25fdXAnO1xuLyoqXG4gKiBJbnRlcmZhY2UgdGhhdCByZXByZXNlbnRzIHRoZSBjcmVkZW50aWFscyByZXR1cm5lZCBieSB7QGxpbmsgRW1haWxBdXRoUHJvdmlkZXJ9IGZvclxuICoge0BsaW5rIFByb3ZpZGVySWR9LlBBU1NXT1JEXG4gKlxuICogQHJlbWFya3NcbiAqIENvdmVycyBib3RoIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX1BBU1NXT1JEIGFuZFxuICoge0BsaW5rIFNpZ25Jbk1ldGhvZH0uRU1BSUxfTElOSy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBFbWFpbEF1dGhDcmVkZW50aWFsIGV4dGVuZHMgQXV0aENyZWRlbnRpYWwge1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIHJlYWRvbmx5IF9lbWFpbDogc3RyaW5nLFxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICByZWFkb25seSBfcGFzc3dvcmQ6IHN0cmluZyxcbiAgICBzaWduSW5NZXRob2Q6IFNpZ25Jbk1ldGhvZCxcbiAgICAvKiogQGludGVybmFsICovXG4gICAgcmVhZG9ubHkgX3RlbmFudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICApIHtcbiAgICBzdXBlcihQcm92aWRlcklkLlBBU1NXT1JELCBzaWduSW5NZXRob2QpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX2Zyb21FbWFpbEFuZFBhc3N3b3JkKFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBFbWFpbEF1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gbmV3IEVtYWlsQXV0aENyZWRlbnRpYWwoXG4gICAgICBlbWFpbCxcbiAgICAgIHBhc3N3b3JkLFxuICAgICAgU2lnbkluTWV0aG9kLkVNQUlMX1BBU1NXT1JEXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tRW1haWxBbmRDb2RlKFxuICAgIGVtYWlsOiBzdHJpbmcsXG4gICAgb29iQ29kZTogc3RyaW5nLFxuICAgIHRlbmFudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbFxuICApOiBFbWFpbEF1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gbmV3IEVtYWlsQXV0aENyZWRlbnRpYWwoXG4gICAgICBlbWFpbCxcbiAgICAgIG9vYkNvZGUsXG4gICAgICBTaWduSW5NZXRob2QuRU1BSUxfTElOSyxcbiAgICAgIHRlbmFudElkXG4gICAgKTtcbiAgfVxuXG4gIC8qKiB7QGluaGVyaXRkb2MgQXV0aENyZWRlbnRpYWwudG9KU09OfSAqL1xuICB0b0pTT04oKTogb2JqZWN0IHtcbiAgICByZXR1cm4ge1xuICAgICAgZW1haWw6IHRoaXMuX2VtYWlsLFxuICAgICAgcGFzc3dvcmQ6IHRoaXMuX3Bhc3N3b3JkLFxuICAgICAgc2lnbkluTWV0aG9kOiB0aGlzLnNpZ25Jbk1ldGhvZCxcbiAgICAgIHRlbmFudElkOiB0aGlzLl90ZW5hbnRJZFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU3RhdGljIG1ldGhvZCB0byBkZXNlcmlhbGl6ZSBhIEpTT04gcmVwcmVzZW50YXRpb24gb2YgYW4gb2JqZWN0IGludG8gYW4ge0BsaW5rICBBdXRoQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSBqc29uIC0gRWl0aGVyIGBvYmplY3RgIG9yIHRoZSBzdHJpbmdpZmllZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JqZWN0LiBXaGVuIHN0cmluZyBpc1xuICAgKiBwcm92aWRlZCwgYEpTT04ucGFyc2VgIHdvdWxkIGJlIGNhbGxlZCBmaXJzdC5cbiAgICpcbiAgICogQHJldHVybnMgSWYgdGhlIEpTT04gaW5wdXQgZG9lcyBub3QgcmVwcmVzZW50IGFuIHtAbGluayBBdXRoQ3JlZGVudGlhbH0sIG51bGwgaXMgcmV0dXJuZWQuXG4gICAqL1xuICBzdGF0aWMgZnJvbUpTT04oanNvbjogb2JqZWN0IHwgc3RyaW5nKTogRW1haWxBdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGNvbnN0IG9iaiA9IHR5cGVvZiBqc29uID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UoanNvbikgOiBqc29uO1xuICAgIGlmIChvYmo/LmVtYWlsICYmIG9iaj8ucGFzc3dvcmQpIHtcbiAgICAgIGlmIChvYmouc2lnbkluTWV0aG9kID09PSBTaWduSW5NZXRob2QuRU1BSUxfUEFTU1dPUkQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zyb21FbWFpbEFuZFBhc3N3b3JkKG9iai5lbWFpbCwgb2JqLnBhc3N3b3JkKTtcbiAgICAgIH0gZWxzZSBpZiAob2JqLnNpZ25Jbk1ldGhvZCA9PT0gU2lnbkluTWV0aG9kLkVNQUlMX0xJTkspIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zyb21FbWFpbEFuZENvZGUob2JqLmVtYWlsLCBvYmoucGFzc3dvcmQsIG9iai50ZW5hbnRJZCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBhc3luYyBfZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgc3dpdGNoICh0aGlzLnNpZ25Jbk1ldGhvZCkge1xuICAgICAgY2FzZSBTaWduSW5NZXRob2QuRU1BSUxfUEFTU1dPUkQ6XG4gICAgICAgIGNvbnN0IHJlcXVlc3Q6IFNpZ25JbldpdGhQYXNzd29yZFJlcXVlc3QgPSB7XG4gICAgICAgICAgcmV0dXJuU2VjdXJlVG9rZW46IHRydWUsXG4gICAgICAgICAgZW1haWw6IHRoaXMuX2VtYWlsLFxuICAgICAgICAgIHBhc3N3b3JkOiB0aGlzLl9wYXNzd29yZCxcbiAgICAgICAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgUmVjYXB0Y2hhQWN0aW9uTmFtZS5TSUdOX0lOX1dJVEhfUEFTU1dPUkQsXG4gICAgICAgICAgc2lnbkluV2l0aFBhc3N3b3JkLFxuICAgICAgICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICAgICAgICApO1xuICAgICAgY2FzZSBTaWduSW5NZXRob2QuRU1BSUxfTElOSzpcbiAgICAgICAgcmV0dXJuIHNpZ25JbldpdGhFbWFpbExpbmsoYXV0aCwge1xuICAgICAgICAgIGVtYWlsOiB0aGlzLl9lbWFpbCxcbiAgICAgICAgICBvb2JDb2RlOiB0aGlzLl9wYXNzd29yZFxuICAgICAgICB9KTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgYXN5bmMgX2xpbmtUb0lkVG9rZW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPElkVG9rZW5SZXNwb25zZT4ge1xuICAgIHN3aXRjaCAodGhpcy5zaWduSW5NZXRob2QpIHtcbiAgICAgIGNhc2UgU2lnbkluTWV0aG9kLkVNQUlMX1BBU1NXT1JEOlxuICAgICAgICBjb25zdCByZXF1ZXN0OiBTaWduVXBSZXF1ZXN0ID0ge1xuICAgICAgICAgIGlkVG9rZW4sXG4gICAgICAgICAgcmV0dXJuU2VjdXJlVG9rZW46IHRydWUsXG4gICAgICAgICAgZW1haWw6IHRoaXMuX2VtYWlsLFxuICAgICAgICAgIHBhc3N3b3JkOiB0aGlzLl9wYXNzd29yZCxcbiAgICAgICAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICAgICAgICBhdXRoLFxuICAgICAgICAgIHJlcXVlc3QsXG4gICAgICAgICAgUmVjYXB0Y2hhQWN0aW9uTmFtZS5TSUdOX1VQX1BBU1NXT1JELFxuICAgICAgICAgIGxpbmtFbWFpbFBhc3N3b3JkLFxuICAgICAgICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICAgICAgICApO1xuICAgICAgY2FzZSBTaWduSW5NZXRob2QuRU1BSUxfTElOSzpcbiAgICAgICAgcmV0dXJuIHNpZ25JbldpdGhFbWFpbExpbmtGb3JMaW5raW5nKGF1dGgsIHtcbiAgICAgICAgICBpZFRva2VuLFxuICAgICAgICAgIGVtYWlsOiB0aGlzLl9lbWFpbCxcbiAgICAgICAgICBvb2JDb2RlOiB0aGlzLl9wYXNzd29yZFxuICAgICAgICB9KTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIF9mYWlsKGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX2dldFJlYXV0aGVudGljYXRpb25SZXNvbHZlcihhdXRoOiBBdXRoSW50ZXJuYWwpOiBQcm9taXNlPElkVG9rZW5SZXNwb25zZT4ge1xuICAgIHJldHVybiB0aGlzLl9nZXRJZFRva2VuUmVzcG9uc2UoYXV0aCk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBFbmRwb2ludCxcbiAgSHR0cE1ldGhvZCxcbiAgX2FkZFRpZElmTmVjZXNzYXJ5LFxuICBfcGVyZm9ybVNpZ25JblJlcXVlc3Rcbn0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgSWRUb2tlbiwgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkluV2l0aElkcFJlcXVlc3Qge1xuICByZXF1ZXN0VXJpOiBzdHJpbmc7XG4gIHBvc3RCb2R5Pzogc3RyaW5nO1xuICBzZXNzaW9uSWQ/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICByZXR1cm5TZWN1cmVUb2tlbjogYm9vbGVhbjtcbiAgcmV0dXJuSWRwQ3JlZGVudGlhbD86IGJvb2xlYW47XG4gIGlkVG9rZW4/OiBJZFRva2VuO1xuICBhdXRvQ3JlYXRlPzogYm9vbGVhbjtcbiAgcGVuZGluZ1Rva2VuPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhJZHBSZXNwb25zZSBleHRlbmRzIElkVG9rZW5SZXNwb25zZSB7XG4gIG9hdXRoQWNjZXNzVG9rZW4/OiBzdHJpbmc7XG4gIG9hdXRoVG9rZW5TZWNyZXQ/OiBzdHJpbmc7XG4gIG5vbmNlPzogc3RyaW5nO1xuICBvYXV0aElkVG9rZW4/OiBzdHJpbmc7XG4gIHBlbmRpbmdUb2tlbj86IHN0cmluZztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbldpdGhJZHAoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25JbldpdGhJZHBSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhJZHBSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFNpZ25JbldpdGhJZHBSZXF1ZXN0LCBTaWduSW5XaXRoSWRwUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNJR05fSU5fV0lUSF9JRFAsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgcXVlcnlzdHJpbmcgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7XG4gIHNpZ25JbldpdGhJZHAsXG4gIFNpZ25JbldpdGhJZHBSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9pZHAnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2F1dGhfY3JlZGVudGlhbCc7XG5cbmNvbnN0IElEUF9SRVFVRVNUX1VSSSA9ICdodHRwOi8vbG9jYWxob3N0JztcblxuZXhwb3J0IGludGVyZmFjZSBPQXV0aENyZWRlbnRpYWxQYXJhbXMge1xuICAvLyBPQXV0aCAyIHVzZXMgZWl0aGVyIGlkIHRva2VuIG9yIGFjY2VzcyB0b2tlblxuICBpZFRva2VuPzogc3RyaW5nIHwgbnVsbDtcbiAgYWNjZXNzVG9rZW4/OiBzdHJpbmcgfCBudWxsO1xuXG4gIC8vIFRoZXNlIGZpZWxkcyBhcmUgdXNlZCB3aXRoIE9BdXRoIDFcbiAgb2F1dGhUb2tlbj86IHN0cmluZztcbiAgc2VjcmV0Pzogc3RyaW5nO1xuICBvYXV0aFRva2VuU2VjcmV0Pzogc3RyaW5nO1xuXG4gIC8vIE5vbmNlIGlzIG9ubHkgc2V0IGlmIHBlbmRpbmdUb2tlbiBpcyBub3QgcHJlc2VudFxuICBub25jZT86IHN0cmluZztcbiAgcGVuZGluZ1Rva2VuPzogc3RyaW5nO1xuXG4gIC8vIFV0aWxpdGllc1xuICBwcm92aWRlcklkOiBzdHJpbmc7XG4gIHNpZ25Jbk1ldGhvZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIE9BdXRoIGNyZWRlbnRpYWxzIHJldHVybmVkIGJ5IGFuIHtAbGluayBPQXV0aFByb3ZpZGVyfS5cbiAqXG4gKiBAcmVtYXJrc1xuICogSW1wbGVtZW50YXRpb25zIHNwZWNpZnkgdGhlIGRldGFpbHMgYWJvdXQgZWFjaCBhdXRoIHByb3ZpZGVyJ3MgY3JlZGVudGlhbCByZXF1aXJlbWVudHMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgT0F1dGhDcmVkZW50aWFsIGV4dGVuZHMgQXV0aENyZWRlbnRpYWwge1xuICAvKipcbiAgICogVGhlIE9BdXRoIElEIHRva2VuIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3JlZGVudGlhbCBpZiBpdCBiZWxvbmdzIHRvIGFuIE9JREMgcHJvdmlkZXIsXG4gICAqIHN1Y2ggYXMgYGdvb2dsZS5jb21gLlxuICAgKiBAcmVhZG9ubHlcbiAgICovXG4gIGlkVG9rZW4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgT0F1dGggYWNjZXNzIHRva2VuIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3JlZGVudGlhbCBpZiBpdCBiZWxvbmdzIHRvIGFuXG4gICAqIHtAbGluayBPQXV0aFByb3ZpZGVyfSwgc3VjaCBhcyBgZmFjZWJvb2suY29tYCwgYHR3aXR0ZXIuY29tYCwgZXRjLlxuICAgKiBAcmVhZG9ubHlcbiAgICovXG4gIGFjY2Vzc1Rva2VuPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIE9BdXRoIGFjY2VzcyB0b2tlbiBzZWNyZXQgYXNzb2NpYXRlZCB3aXRoIHRoZSBjcmVkZW50aWFsIGlmIGl0IGJlbG9uZ3MgdG8gYW4gT0F1dGggMS4wXG4gICAqIHByb3ZpZGVyLCBzdWNoIGFzIGB0d2l0dGVyLmNvbWAuXG4gICAqIEByZWFkb25seVxuICAgKi9cbiAgc2VjcmV0Pzogc3RyaW5nO1xuXG4gIHByaXZhdGUgbm9uY2U/OiBzdHJpbmc7XG4gIHByaXZhdGUgcGVuZGluZ1Rva2VuOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAvKiogQGludGVybmFsICovXG4gIHN0YXRpYyBfZnJvbVBhcmFtcyhwYXJhbXM6IE9BdXRoQ3JlZGVudGlhbFBhcmFtcyk6IE9BdXRoQ3JlZGVudGlhbCB7XG4gICAgY29uc3QgY3JlZCA9IG5ldyBPQXV0aENyZWRlbnRpYWwocGFyYW1zLnByb3ZpZGVySWQsIHBhcmFtcy5zaWduSW5NZXRob2QpO1xuXG4gICAgaWYgKHBhcmFtcy5pZFRva2VuIHx8IHBhcmFtcy5hY2Nlc3NUb2tlbikge1xuICAgICAgLy8gT0F1dGggMiBhbmQgZWl0aGVyIElEIHRva2VuIG9yIGFjY2VzcyB0b2tlbi5cbiAgICAgIGlmIChwYXJhbXMuaWRUb2tlbikge1xuICAgICAgICBjcmVkLmlkVG9rZW4gPSBwYXJhbXMuaWRUb2tlbjtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5hY2Nlc3NUb2tlbikge1xuICAgICAgICBjcmVkLmFjY2Vzc1Rva2VuID0gcGFyYW1zLmFjY2Vzc1Rva2VuO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgbm9uY2UgaWYgYXZhaWxhYmxlIGFuZCBubyBwZW5kaW5nVG9rZW4gaXMgcHJlc2VudC5cbiAgICAgIGlmIChwYXJhbXMubm9uY2UgJiYgIXBhcmFtcy5wZW5kaW5nVG9rZW4pIHtcbiAgICAgICAgY3JlZC5ub25jZSA9IHBhcmFtcy5ub25jZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5wZW5kaW5nVG9rZW4pIHtcbiAgICAgICAgY3JlZC5wZW5kaW5nVG9rZW4gPSBwYXJhbXMucGVuZGluZ1Rva2VuO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW1zLm9hdXRoVG9rZW4gJiYgcGFyYW1zLm9hdXRoVG9rZW5TZWNyZXQpIHtcbiAgICAgIC8vIE9BdXRoIDEgYW5kIE9BdXRoIHRva2VuIHdpdGggdG9rZW4gc2VjcmV0XG4gICAgICBjcmVkLmFjY2Vzc1Rva2VuID0gcGFyYW1zLm9hdXRoVG9rZW47XG4gICAgICBjcmVkLnNlY3JldCA9IHBhcmFtcy5vYXV0aFRva2VuU2VjcmV0O1xuICAgIH0gZWxzZSB7XG4gICAgICBfZmFpbChBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY3JlZDtcbiAgfVxuXG4gIC8qKiB7QGluaGVyaXRkb2MgQXV0aENyZWRlbnRpYWwudG9KU09OfSAgKi9cbiAgdG9KU09OKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkVG9rZW46IHRoaXMuaWRUb2tlbixcbiAgICAgIGFjY2Vzc1Rva2VuOiB0aGlzLmFjY2Vzc1Rva2VuLFxuICAgICAgc2VjcmV0OiB0aGlzLnNlY3JldCxcbiAgICAgIG5vbmNlOiB0aGlzLm5vbmNlLFxuICAgICAgcGVuZGluZ1Rva2VuOiB0aGlzLnBlbmRpbmdUb2tlbixcbiAgICAgIHByb3ZpZGVySWQ6IHRoaXMucHJvdmlkZXJJZCxcbiAgICAgIHNpZ25Jbk1ldGhvZDogdGhpcy5zaWduSW5NZXRob2RcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXRpYyBtZXRob2QgdG8gZGVzZXJpYWxpemUgYSBKU09OIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdCBpbnRvIGFuXG4gICAqIHtAbGluayAgQXV0aENyZWRlbnRpYWx9LlxuICAgKlxuICAgKiBAcGFyYW0ganNvbiAtIElucHV0IGNhbiBiZSBlaXRoZXIgT2JqZWN0IG9yIHRoZSBzdHJpbmdpZmllZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgb2JqZWN0LlxuICAgKiBXaGVuIHN0cmluZyBpcyBwcm92aWRlZCwgSlNPTi5wYXJzZSB3b3VsZCBiZSBjYWxsZWQgZmlyc3QuXG4gICAqXG4gICAqIEByZXR1cm5zIElmIHRoZSBKU09OIGlucHV0IGRvZXMgbm90IHJlcHJlc2VudCBhbiB7QGxpbmsgIEF1dGhDcmVkZW50aWFsfSwgbnVsbCBpcyByZXR1cm5lZC5cbiAgICovXG4gIHN0YXRpYyBmcm9tSlNPTihqc29uOiBzdHJpbmcgfCBvYmplY3QpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICBjb25zdCBvYmogPSB0eXBlb2YganNvbiA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKGpzb24pIDoganNvbjtcbiAgICBjb25zdCB7IHByb3ZpZGVySWQsIHNpZ25Jbk1ldGhvZCwgLi4ucmVzdCB9OiBPQXV0aENyZWRlbnRpYWxQYXJhbXMgPSBvYmo7XG4gICAgaWYgKCFwcm92aWRlcklkIHx8ICFzaWduSW5NZXRob2QpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGNyZWQgPSBuZXcgT0F1dGhDcmVkZW50aWFsKHByb3ZpZGVySWQsIHNpZ25Jbk1ldGhvZCk7XG4gICAgY3JlZC5pZFRva2VuID0gcmVzdC5pZFRva2VuIHx8IHVuZGVmaW5lZDtcbiAgICBjcmVkLmFjY2Vzc1Rva2VuID0gcmVzdC5hY2Nlc3NUb2tlbiB8fCB1bmRlZmluZWQ7XG4gICAgY3JlZC5zZWNyZXQgPSByZXN0LnNlY3JldDtcbiAgICBjcmVkLm5vbmNlID0gcmVzdC5ub25jZTtcbiAgICBjcmVkLnBlbmRpbmdUb2tlbiA9IHJlc3QucGVuZGluZ1Rva2VuIHx8IG51bGw7XG4gICAgcmV0dXJuIGNyZWQ7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9nZXRJZFRva2VuUmVzcG9uc2UoYXV0aDogQXV0aEludGVybmFsKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QoKTtcbiAgICByZXR1cm4gc2lnbkluV2l0aElkcChhdXRoLCByZXF1ZXN0KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX2xpbmtUb0lkVG9rZW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGlkVG9rZW46IHN0cmluZ1xuICApOiBQcm9taXNlPElkVG9rZW5SZXNwb25zZT4ge1xuICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLmJ1aWxkUmVxdWVzdCgpO1xuICAgIHJlcXVlc3QuaWRUb2tlbiA9IGlkVG9rZW47XG4gICAgcmV0dXJuIHNpZ25JbldpdGhJZHAoYXV0aCwgcmVxdWVzdCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9nZXRSZWF1dGhlbnRpY2F0aW9uUmVzb2x2ZXIoYXV0aDogQXV0aEludGVybmFsKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QoKTtcbiAgICByZXF1ZXN0LmF1dG9DcmVhdGUgPSBmYWxzZTtcbiAgICByZXR1cm4gc2lnbkluV2l0aElkcChhdXRoLCByZXF1ZXN0KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRSZXF1ZXN0KCk6IFNpZ25JbldpdGhJZHBSZXF1ZXN0IHtcbiAgICBjb25zdCByZXF1ZXN0OiBTaWduSW5XaXRoSWRwUmVxdWVzdCA9IHtcbiAgICAgIHJlcXVlc3RVcmk6IElEUF9SRVFVRVNUX1VSSSxcbiAgICAgIHJldHVyblNlY3VyZVRva2VuOiB0cnVlXG4gICAgfTtcblxuICAgIGlmICh0aGlzLnBlbmRpbmdUb2tlbikge1xuICAgICAgcmVxdWVzdC5wZW5kaW5nVG9rZW4gPSB0aGlzLnBlbmRpbmdUb2tlbjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcG9zdEJvZHk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAgIGlmICh0aGlzLmlkVG9rZW4pIHtcbiAgICAgICAgcG9zdEJvZHlbJ2lkX3Rva2VuJ10gPSB0aGlzLmlkVG9rZW47XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5hY2Nlc3NUb2tlbikge1xuICAgICAgICBwb3N0Qm9keVsnYWNjZXNzX3Rva2VuJ10gPSB0aGlzLmFjY2Vzc1Rva2VuO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuc2VjcmV0KSB7XG4gICAgICAgIHBvc3RCb2R5WydvYXV0aF90b2tlbl9zZWNyZXQnXSA9IHRoaXMuc2VjcmV0O1xuICAgICAgfVxuXG4gICAgICBwb3N0Qm9keVsncHJvdmlkZXJJZCddID0gdGhpcy5wcm92aWRlcklkO1xuICAgICAgaWYgKHRoaXMubm9uY2UgJiYgIXRoaXMucGVuZGluZ1Rva2VuKSB7XG4gICAgICAgIHBvc3RCb2R5Wydub25jZSddID0gdGhpcy5ub25jZTtcbiAgICAgIH1cblxuICAgICAgcmVxdWVzdC5wb3N0Qm9keSA9IHF1ZXJ5c3RyaW5nKHBvc3RCb2R5KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVxdWVzdDtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEVuZHBvaW50LFxuICBIdHRwTWV0aG9kLFxuICBSZWNhcHRjaGFDbGllbnRUeXBlLFxuICBSZWNhcHRjaGFWZXJzaW9uLFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIF9tYWtlVGFnZ2VkRXJyb3IsXG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgX3BlcmZvcm1TaWduSW5SZXF1ZXN0XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi8uLi9jb3JlL2Vycm9ycyc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBTZXJ2ZXJFcnJvciwgU2VydmVyRXJyb3JNYXAgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlcXVlc3Qge1xuICBwaG9uZU51bWJlcjogc3RyaW5nO1xuICAvLyByZUNBUFRDSEEgdjIgdG9rZW5cbiAgcmVjYXB0Y2hhVG9rZW4/OiBzdHJpbmc7XG4gIHRlbmFudElkPzogc3RyaW5nO1xuICAvLyByZUNBUFRDSEEgRW50ZXJwcmlzZSB0b2tlblxuICBjYXB0Y2hhUmVzcG9uc2U/OiBzdHJpbmc7XG4gIGNsaWVudFR5cGU/OiBSZWNhcHRjaGFDbGllbnRUeXBlO1xuICByZWNhcHRjaGFWZXJzaW9uPzogUmVjYXB0Y2hhVmVyc2lvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZW5kUGhvbmVWZXJpZmljYXRpb25Db2RlUmVzcG9uc2Uge1xuICBzZXNzaW9uSW5mbzogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlcXVlc3Rcbik6IFByb21pc2U8U2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlcXVlc3QsXG4gICAgU2VuZFBob25lVmVyaWZpY2F0aW9uQ29kZVJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0VORF9WRVJJRklDQVRJT05fQ09ERSxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IHtcbiAgdGVtcG9yYXJ5UHJvb2Y/OiBzdHJpbmc7XG4gIHBob25lTnVtYmVyPzogc3RyaW5nO1xuICBzZXNzaW9uSW5mbz86IHN0cmluZztcbiAgY29kZT86IHN0cmluZztcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlua1dpdGhQaG9uZU51bWJlclJlcXVlc3RcbiAgZXh0ZW5kcyBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IHtcbiAgaWRUb2tlbjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHtcbiAgdGVtcG9yYXJ5UHJvb2Y/OiBzdHJpbmc7XG4gIHBob25lTnVtYmVyPzogc3RyaW5nO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aFBob25lTnVtYmVyKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybVNpZ25JblJlcXVlc3Q8XG4gICAgU2lnbkluV2l0aFBob25lTnVtYmVyUmVxdWVzdCxcbiAgICBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXNwb25zZVxuICA+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNJR05fSU5fV0lUSF9QSE9ORV9OVU1CRVIsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaW5rV2l0aFBob25lTnVtYmVyKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBMaW5rV2l0aFBob25lTnVtYmVyUmVxdWVzdFxuKTogUHJvbWlzZTxTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXNwb25zZT4ge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9wZXJmb3JtU2lnbkluUmVxdWVzdDxcbiAgICBMaW5rV2l0aFBob25lTnVtYmVyUmVxdWVzdCxcbiAgICBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXNwb25zZVxuICA+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNJR05fSU5fV0lUSF9QSE9ORV9OVU1CRVIsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG4gIGlmIChyZXNwb25zZS50ZW1wb3JhcnlQcm9vZikge1xuICAgIHRocm93IF9tYWtlVGFnZ2VkRXJyb3IoYXV0aCwgQXV0aEVycm9yQ29kZS5ORUVEX0NPTkZJUk1BVElPTiwgcmVzcG9uc2UpO1xuICB9XG4gIHJldHVybiByZXNwb25zZTtcbn1cblxuaW50ZXJmYWNlIFZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmdSZXF1ZXN0XG4gIGV4dGVuZHMgU2lnbkluV2l0aFBob25lTnVtYmVyUmVxdWVzdCB7XG4gIG9wZXJhdGlvbjogJ1JFQVVUSCc7XG59XG5cbmNvbnN0IFZFUklGWV9QSE9ORV9OVU1CRVJfRk9SX0VYSVNUSU5HX0VSUk9SX01BUF86IFBhcnRpYWw8XG4gIFNlcnZlckVycm9yTWFwPFNlcnZlckVycm9yPlxuPiA9IHtcbiAgW1NlcnZlckVycm9yLlVTRVJfTk9UX0ZPVU5EXTogQXV0aEVycm9yQ29kZS5VU0VSX0RFTEVURURcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlQaG9uZU51bWJlckZvckV4aXN0aW5nKFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0XG4pOiBQcm9taXNlPFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlPiB7XG4gIGNvbnN0IGFwaVJlcXVlc3Q6IFZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmdSZXF1ZXN0ID0ge1xuICAgIC4uLnJlcXVlc3QsXG4gICAgb3BlcmF0aW9uOiAnUkVBVVRIJ1xuICB9O1xuICByZXR1cm4gX3BlcmZvcm1TaWduSW5SZXF1ZXN0PFxuICAgIFZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmdSZXF1ZXN0LFxuICAgIFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9JTl9XSVRIX1BIT05FX05VTUJFUixcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgYXBpUmVxdWVzdCksXG4gICAgVkVSSUZZX1BIT05FX05VTUJFUl9GT1JfRVhJU1RJTkdfRVJST1JfTUFQX1xuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFByb3ZpZGVySWQsIFNpZ25Jbk1ldGhvZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuaW1wb3J0IHsgUGhvbmVPck9hdXRoVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9tZmEnO1xuaW1wb3J0IHtcbiAgbGlua1dpdGhQaG9uZU51bWJlcixcbiAgc2lnbkluV2l0aFBob25lTnVtYmVyLFxuICBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0LFxuICB2ZXJpZnlQaG9uZU51bWJlckZvckV4aXN0aW5nXG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9zbXMnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vYXV0aF9jcmVkZW50aWFsJztcblxuZXhwb3J0IGludGVyZmFjZSBQaG9uZUF1dGhDcmVkZW50aWFsUGFyYW1ldGVycyB7XG4gIHZlcmlmaWNhdGlvbklkPzogc3RyaW5nO1xuICB2ZXJpZmljYXRpb25Db2RlPzogc3RyaW5nO1xuICBwaG9uZU51bWJlcj86IHN0cmluZztcbiAgdGVtcG9yYXJ5UHJvb2Y/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgY3JlZGVudGlhbHMgcmV0dXJuZWQgYnkge0BsaW5rIFBob25lQXV0aFByb3ZpZGVyfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBQaG9uZUF1dGhDcmVkZW50aWFsIGV4dGVuZHMgQXV0aENyZWRlbnRpYWwge1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcGFyYW1zOiBQaG9uZUF1dGhDcmVkZW50aWFsUGFyYW1ldGVycykge1xuICAgIHN1cGVyKFByb3ZpZGVySWQuUEhPTkUsIFNpZ25Jbk1ldGhvZC5QSE9ORSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHN0YXRpYyBfZnJvbVZlcmlmaWNhdGlvbihcbiAgICB2ZXJpZmljYXRpb25JZDogc3RyaW5nLFxuICAgIHZlcmlmaWNhdGlvbkNvZGU6IHN0cmluZ1xuICApOiBQaG9uZUF1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gbmV3IFBob25lQXV0aENyZWRlbnRpYWwoeyB2ZXJpZmljYXRpb25JZCwgdmVyaWZpY2F0aW9uQ29kZSB9KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tVG9rZW5SZXNwb25zZShcbiAgICBwaG9uZU51bWJlcjogc3RyaW5nLFxuICAgIHRlbXBvcmFyeVByb29mOiBzdHJpbmdcbiAgKTogUGhvbmVBdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIG5ldyBQaG9uZUF1dGhDcmVkZW50aWFsKHsgcGhvbmVOdW1iZXIsIHRlbXBvcmFyeVByb29mIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8UGhvbmVPck9hdXRoVG9rZW5SZXNwb25zZT4ge1xuICAgIHJldHVybiBzaWduSW5XaXRoUGhvbmVOdW1iZXIoYXV0aCwgdGhpcy5fbWFrZVZlcmlmaWNhdGlvblJlcXVlc3QoKSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9saW5rVG9JZFRva2VuKFxuICAgIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBpZFRva2VuOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICByZXR1cm4gbGlua1dpdGhQaG9uZU51bWJlcihhdXRoLCB7XG4gICAgICBpZFRva2VuLFxuICAgICAgLi4udGhpcy5fbWFrZVZlcmlmaWNhdGlvblJlcXVlc3QoKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0UmVhdXRoZW50aWNhdGlvblJlc29sdmVyKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgcmV0dXJuIHZlcmlmeVBob25lTnVtYmVyRm9yRXhpc3RpbmcoYXV0aCwgdGhpcy5fbWFrZVZlcmlmaWNhdGlvblJlcXVlc3QoKSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9tYWtlVmVyaWZpY2F0aW9uUmVxdWVzdCgpOiBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IHtcbiAgICBjb25zdCB7IHRlbXBvcmFyeVByb29mLCBwaG9uZU51bWJlciwgdmVyaWZpY2F0aW9uSWQsIHZlcmlmaWNhdGlvbkNvZGUgfSA9XG4gICAgICB0aGlzLnBhcmFtcztcbiAgICBpZiAodGVtcG9yYXJ5UHJvb2YgJiYgcGhvbmVOdW1iZXIpIHtcbiAgICAgIHJldHVybiB7IHRlbXBvcmFyeVByb29mLCBwaG9uZU51bWJlciB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzZXNzaW9uSW5mbzogdmVyaWZpY2F0aW9uSWQsXG4gICAgICBjb2RlOiB2ZXJpZmljYXRpb25Db2RlXG4gICAgfTtcbiAgfVxuXG4gIC8qKiB7QGluaGVyaXRkb2MgQXV0aENyZWRlbnRpYWwudG9KU09OfSAqL1xuICB0b0pTT04oKTogb2JqZWN0IHtcbiAgICBjb25zdCBvYmo6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBwcm92aWRlcklkOiB0aGlzLnByb3ZpZGVySWRcbiAgICB9O1xuICAgIGlmICh0aGlzLnBhcmFtcy5waG9uZU51bWJlcikge1xuICAgICAgb2JqLnBob25lTnVtYmVyID0gdGhpcy5wYXJhbXMucGhvbmVOdW1iZXI7XG4gICAgfVxuICAgIGlmICh0aGlzLnBhcmFtcy50ZW1wb3JhcnlQcm9vZikge1xuICAgICAgb2JqLnRlbXBvcmFyeVByb29mID0gdGhpcy5wYXJhbXMudGVtcG9yYXJ5UHJvb2Y7XG4gICAgfVxuICAgIGlmICh0aGlzLnBhcmFtcy52ZXJpZmljYXRpb25Db2RlKSB7XG4gICAgICBvYmoudmVyaWZpY2F0aW9uQ29kZSA9IHRoaXMucGFyYW1zLnZlcmlmaWNhdGlvbkNvZGU7XG4gICAgfVxuICAgIGlmICh0aGlzLnBhcmFtcy52ZXJpZmljYXRpb25JZCkge1xuICAgICAgb2JqLnZlcmlmaWNhdGlvbklkID0gdGhpcy5wYXJhbXMudmVyaWZpY2F0aW9uSWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIC8qKiBHZW5lcmF0ZXMgYSBwaG9uZSBjcmVkZW50aWFsIGJhc2VkIG9uIGEgcGxhaW4gb2JqZWN0IG9yIGEgSlNPTiBzdHJpbmcuICovXG4gIHN0YXRpYyBmcm9tSlNPTihqc29uOiBvYmplY3QgfCBzdHJpbmcpOiBQaG9uZUF1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgaWYgKHR5cGVvZiBqc29uID09PSAnc3RyaW5nJykge1xuICAgICAganNvbiA9IEpTT04ucGFyc2UoanNvbik7XG4gICAgfVxuXG4gICAgY29uc3QgeyB2ZXJpZmljYXRpb25JZCwgdmVyaWZpY2F0aW9uQ29kZSwgcGhvbmVOdW1iZXIsIHRlbXBvcmFyeVByb29mIH0gPVxuICAgICAganNvbiBhcyB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuICAgIGlmIChcbiAgICAgICF2ZXJpZmljYXRpb25Db2RlICYmXG4gICAgICAhdmVyaWZpY2F0aW9uSWQgJiZcbiAgICAgICFwaG9uZU51bWJlciAmJlxuICAgICAgIXRlbXBvcmFyeVByb29mXG4gICAgKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFBob25lQXV0aENyZWRlbnRpYWwoe1xuICAgICAgdmVyaWZpY2F0aW9uSWQsXG4gICAgICB2ZXJpZmljYXRpb25Db2RlLFxuICAgICAgcGhvbmVOdW1iZXIsXG4gICAgICB0ZW1wb3JhcnlQcm9vZlxuICAgIH0pO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgZXh0cmFjdFF1ZXJ5c3RyaW5nLCBxdWVyeXN0cmluZ0RlY29kZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEFjdGlvbkNvZGVPcGVyYXRpb24gfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuL3V0aWwvYXNzZXJ0JztcblxuLyoqXG4gKiBFbnVtcyBmb3IgZmllbGRzIGluIFVSTCBxdWVyeSBzdHJpbmcuXG4gKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuY29uc3QgZW51bSBRdWVyeUZpZWxkIHtcbiAgQVBJX0tFWSA9ICdhcGlLZXknLFxuICBDT0RFID0gJ29vYkNvZGUnLFxuICBDT05USU5VRV9VUkwgPSAnY29udGludWVVcmwnLFxuICBMQU5HVUFHRV9DT0RFID0gJ2xhbmcnLFxuICBNT0RFID0gJ21vZGUnLFxuICBURU5BTlRfSUQgPSAndGVuYW50SWQnXG59XG5cbi8qKlxuICogTWFwcyB0aGUgbW9kZSBzdHJpbmcgaW4gYWN0aW9uIGNvZGUgVVJMIHRvIEFjdGlvbiBDb2RlIEluZm8gb3BlcmF0aW9uLlxuICpcbiAqIEBwYXJhbSBtb2RlXG4gKi9cbmZ1bmN0aW9uIHBhcnNlTW9kZShtb2RlOiBzdHJpbmcgfCBudWxsKTogQWN0aW9uQ29kZU9wZXJhdGlvbiB8IG51bGwge1xuICBzd2l0Y2ggKG1vZGUpIHtcbiAgICBjYXNlICdyZWNvdmVyRW1haWwnOlxuICAgICAgcmV0dXJuIEFjdGlvbkNvZGVPcGVyYXRpb24uUkVDT1ZFUl9FTUFJTDtcbiAgICBjYXNlICdyZXNldFBhc3N3b3JkJzpcbiAgICAgIHJldHVybiBBY3Rpb25Db2RlT3BlcmF0aW9uLlBBU1NXT1JEX1JFU0VUO1xuICAgIGNhc2UgJ3NpZ25Jbic6XG4gICAgICByZXR1cm4gQWN0aW9uQ29kZU9wZXJhdGlvbi5FTUFJTF9TSUdOSU47XG4gICAgY2FzZSAndmVyaWZ5RW1haWwnOlxuICAgICAgcmV0dXJuIEFjdGlvbkNvZGVPcGVyYXRpb24uVkVSSUZZX0VNQUlMO1xuICAgIGNhc2UgJ3ZlcmlmeUFuZENoYW5nZUVtYWlsJzpcbiAgICAgIHJldHVybiBBY3Rpb25Db2RlT3BlcmF0aW9uLlZFUklGWV9BTkRfQ0hBTkdFX0VNQUlMO1xuICAgIGNhc2UgJ3JldmVydFNlY29uZEZhY3RvckFkZGl0aW9uJzpcbiAgICAgIHJldHVybiBBY3Rpb25Db2RlT3BlcmF0aW9uLlJFVkVSVF9TRUNPTkRfRkFDVE9SX0FERElUSU9OO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vKipcbiAqIEhlbHBlciB0byBwYXJzZSBGREwgbGlua3NcbiAqXG4gKiBAcGFyYW0gdXJsXG4gKi9cbmZ1bmN0aW9uIHBhcnNlRGVlcExpbmsodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBsaW5rID0gcXVlcnlzdHJpbmdEZWNvZGUoZXh0cmFjdFF1ZXJ5c3RyaW5nKHVybCkpWydsaW5rJ107XG5cbiAgLy8gRG91YmxlIGxpbmsgY2FzZSAoYXV0b21hdGljIHJlZGlyZWN0KS5cbiAgY29uc3QgZG91YmxlRGVlcExpbmsgPSBsaW5rXG4gICAgPyBxdWVyeXN0cmluZ0RlY29kZShleHRyYWN0UXVlcnlzdHJpbmcobGluaykpWydkZWVwX2xpbmtfaWQnXVxuICAgIDogbnVsbDtcbiAgLy8gaU9TIGN1c3RvbSBzY2hlbWUgbGlua3MuXG4gIGNvbnN0IGlPU0RlZXBMaW5rID0gcXVlcnlzdHJpbmdEZWNvZGUoZXh0cmFjdFF1ZXJ5c3RyaW5nKHVybCkpW1xuICAgICdkZWVwX2xpbmtfaWQnXG4gIF07XG4gIGNvbnN0IGlPU0RvdWJsZURlZXBMaW5rID0gaU9TRGVlcExpbmtcbiAgICA/IHF1ZXJ5c3RyaW5nRGVjb2RlKGV4dHJhY3RRdWVyeXN0cmluZyhpT1NEZWVwTGluaykpWydsaW5rJ11cbiAgICA6IG51bGw7XG4gIHJldHVybiBpT1NEb3VibGVEZWVwTGluayB8fCBpT1NEZWVwTGluayB8fCBkb3VibGVEZWVwTGluayB8fCBsaW5rIHx8IHVybDtcbn1cblxuLyoqXG4gKiBBIHV0aWxpdHkgY2xhc3MgdG8gcGFyc2UgZW1haWwgYWN0aW9uIFVSTHMgc3VjaCBhcyBwYXNzd29yZCByZXNldCwgZW1haWwgdmVyaWZpY2F0aW9uLFxuICogZW1haWwgbGluayBzaWduIGluLCBldGMuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgQWN0aW9uQ29kZVVSTCB7XG4gIC8qKlxuICAgKiBUaGUgQVBJIGtleSBvZiB0aGUgZW1haWwgYWN0aW9uIGxpbmsuXG4gICAqL1xuICByZWFkb25seSBhcGlLZXk6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBhY3Rpb24gY29kZSBvZiB0aGUgZW1haWwgYWN0aW9uIGxpbmsuXG4gICAqL1xuICByZWFkb25seSBjb2RlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgY29udGludWUgVVJMIG9mIHRoZSBlbWFpbCBhY3Rpb24gbGluay4gTnVsbCBpZiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSBjb250aW51ZVVybDogc3RyaW5nIHwgbnVsbDtcbiAgLyoqXG4gICAqIFRoZSBsYW5ndWFnZSBjb2RlIG9mIHRoZSBlbWFpbCBhY3Rpb24gbGluay4gTnVsbCBpZiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSBsYW5ndWFnZUNvZGU6IHN0cmluZyB8IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgYWN0aW9uIHBlcmZvcm1lZCBieSB0aGUgZW1haWwgYWN0aW9uIGxpbmsuIEl0IHJldHVybnMgZnJvbSBvbmUgb2YgdGhlIHR5cGVzIGZyb21cbiAgICoge0BsaW5rIEFjdGlvbkNvZGVJbmZvfVxuICAgKi9cbiAgcmVhZG9ubHkgb3BlcmF0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdGVuYW50IElEIG9mIHRoZSBlbWFpbCBhY3Rpb24gbGluay4gTnVsbCBpZiB0aGUgZW1haWwgYWN0aW9uIGlzIGZyb20gdGhlIHBhcmVudCBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgdGVuYW50SWQ6IHN0cmluZyB8IG51bGw7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBhY3Rpb25MaW5rIC0gVGhlIGxpbmsgZnJvbSB3aGljaCB0byBleHRyYWN0IHRoZSBVUkwuXG4gICAqIEByZXR1cm5zIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVVSTH0gb2JqZWN0LCBvciBudWxsIGlmIHRoZSBsaW5rIGlzIGludmFsaWQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgY29uc3RydWN0b3IoYWN0aW9uTGluazogc3RyaW5nKSB7XG4gICAgY29uc3Qgc2VhcmNoUGFyYW1zID0gcXVlcnlzdHJpbmdEZWNvZGUoZXh0cmFjdFF1ZXJ5c3RyaW5nKGFjdGlvbkxpbmspKTtcbiAgICBjb25zdCBhcGlLZXkgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5BUElfS0VZXSA/PyBudWxsO1xuICAgIGNvbnN0IGNvZGUgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5DT0RFXSA/PyBudWxsO1xuICAgIGNvbnN0IG9wZXJhdGlvbiA9IHBhcnNlTW9kZShzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5NT0RFXSA/PyBudWxsKTtcbiAgICAvLyBWYWxpZGF0ZSBBUEkga2V5LCBjb2RlIGFuZCBtb2RlLlxuICAgIF9hc3NlcnQoYXBpS2V5ICYmIGNvZGUgJiYgb3BlcmF0aW9uLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICB0aGlzLmFwaUtleSA9IGFwaUtleTtcbiAgICB0aGlzLm9wZXJhdGlvbiA9IG9wZXJhdGlvbjtcbiAgICB0aGlzLmNvZGUgPSBjb2RlO1xuICAgIHRoaXMuY29udGludWVVcmwgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5DT05USU5VRV9VUkxdID8/IG51bGw7XG4gICAgdGhpcy5sYW5ndWFnZUNvZGUgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5MQU5HVUFHRV9DT0RFXSA/PyBudWxsO1xuICAgIHRoaXMudGVuYW50SWQgPSBzZWFyY2hQYXJhbXNbUXVlcnlGaWVsZC5URU5BTlRfSURdID8/IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSBlbWFpbCBhY3Rpb24gbGluayBzdHJpbmcgYW5kIHJldHVybnMgYW4ge0BsaW5rIEFjdGlvbkNvZGVVUkx9IGlmIHRoZSBsaW5rIGlzIHZhbGlkLFxuICAgKiBvdGhlcndpc2UgcmV0dXJucyBudWxsLlxuICAgKlxuICAgKiBAcGFyYW0gbGluayAgLSBUaGUgZW1haWwgYWN0aW9uIGxpbmsgc3RyaW5nLlxuICAgKiBAcmV0dXJucyBUaGUge0BsaW5rIEFjdGlvbkNvZGVVUkx9IG9iamVjdCwgb3IgbnVsbCBpZiB0aGUgbGluayBpcyBpbnZhbGlkLlxuICAgKlxuICAgKiBAcHVibGljXG4gICAqL1xuICBzdGF0aWMgcGFyc2VMaW5rKGxpbms6IHN0cmluZyk6IEFjdGlvbkNvZGVVUkwgfCBudWxsIHtcbiAgICBjb25zdCBhY3Rpb25MaW5rID0gcGFyc2VEZWVwTGluayhsaW5rKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIG5ldyBBY3Rpb25Db2RlVVJMKGFjdGlvbkxpbmspO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUGFyc2VzIHRoZSBlbWFpbCBhY3Rpb24gbGluayBzdHJpbmcgYW5kIHJldHVybnMgYW4ge0BsaW5rIEFjdGlvbkNvZGVVUkx9IGlmXG4gKiB0aGUgbGluayBpcyB2YWxpZCwgb3RoZXJ3aXNlIHJldHVybnMgbnVsbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFjdGlvbkNvZGVVUkwobGluazogc3RyaW5nKTogQWN0aW9uQ29kZVVSTCB8IG51bGwge1xuICByZXR1cm4gQWN0aW9uQ29kZVVSTC5wYXJzZUxpbmsobGluayk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUHJvdmlkZXJJZCwgU2lnbkluTWV0aG9kIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgQWN0aW9uQ29kZVVSTCB9IGZyb20gJy4uL2FjdGlvbl9jb2RlX3VybCc7XG5pbXBvcnQgeyBFbWFpbEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvZW1haWwnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBfYXNzZXJ0IH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBnZW5lcmF0aW5nIHtAbGluayBFbWFpbEF1dGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBFbWFpbEF1dGhQcm92aWRlciBpbXBsZW1lbnRzIEF1dGhQcm92aWRlciB7XG4gIC8qKlxuICAgKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5QQVNTV09SRCwgZXZlbiBmb3IgZW1haWwgbGluay5cbiAgICovXG4gIHN0YXRpYyByZWFkb25seSBQUk9WSURFUl9JRDogJ3Bhc3N3b3JkJyA9IFByb3ZpZGVySWQuUEFTU1dPUkQ7XG4gIC8qKlxuICAgKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX1BBU1NXT1JELlxuICAgKi9cbiAgc3RhdGljIHJlYWRvbmx5IEVNQUlMX1BBU1NXT1JEX1NJR05fSU5fTUVUSE9EOiAncGFzc3dvcmQnID1cbiAgICBTaWduSW5NZXRob2QuRU1BSUxfUEFTU1dPUkQ7XG4gIC8qKlxuICAgKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX0xJTksuXG4gICAqL1xuICBzdGF0aWMgcmVhZG9ubHkgRU1BSUxfTElOS19TSUdOX0lOX01FVEhPRDogJ2VtYWlsTGluaycgPVxuICAgIFNpZ25Jbk1ldGhvZC5FTUFJTF9MSU5LO1xuICAvKipcbiAgICogQWx3YXlzIHNldCB0byB7QGxpbmsgUHJvdmlkZXJJZH0uUEFTU1dPUkQsIGV2ZW4gZm9yIGVtYWlsIGxpbmsuXG4gICAqL1xuICByZWFkb25seSBwcm92aWRlcklkID0gRW1haWxBdXRoUHJvdmlkZXIuUFJPVklERVJfSUQ7XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgYW4ge0BsaW5rIEF1dGhDcmVkZW50aWFsfSB1c2luZyBhbiBlbWFpbCBhbmQgcGFzc3dvcmQuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGphdmFzY3JpcHRcbiAgICogY29uc3QgYXV0aENyZWRlbnRpYWwgPSBFbWFpbEF1dGhQcm92aWRlci5jcmVkZW50aWFsKGVtYWlsLCBwYXNzd29yZCk7XG4gICAqIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgc2lnbkluV2l0aENyZWRlbnRpYWwoYXV0aCwgYXV0aENyZWRlbnRpYWwpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgamF2YXNjcmlwdFxuICAgKiBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IHNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkKGF1dGgsIGVtYWlsLCBwYXNzd29yZCk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAcGFyYW0gZW1haWwgLSBFbWFpbCBhZGRyZXNzLlxuICAgKiBAcGFyYW0gcGFzc3dvcmQgLSBVc2VyIGFjY291bnQgcGFzc3dvcmQuXG4gICAqIEByZXR1cm5zIFRoZSBhdXRoIHByb3ZpZGVyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbChlbWFpbDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogRW1haWxBdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIEVtYWlsQXV0aENyZWRlbnRpYWwuX2Zyb21FbWFpbEFuZFBhc3N3b3JkKGVtYWlsLCBwYXNzd29yZCk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBhbiB7QGxpbmsgQXV0aENyZWRlbnRpYWx9IHVzaW5nIGFuIGVtYWlsIGFuZCBhbiBlbWFpbCBsaW5rIGFmdGVyIGEgc2lnbiBpbiB3aXRoXG4gICAqIGVtYWlsIGxpbmsgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqYXZhc2NyaXB0XG4gICAqIGNvbnN0IGF1dGhDcmVkZW50aWFsID0gRW1haWxBdXRoUHJvdmlkZXIuY3JlZGVudGlhbFdpdGhMaW5rKGF1dGgsIGVtYWlsLCBlbWFpbExpbmspO1xuICAgKiBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IHNpZ25JbldpdGhDcmVkZW50aWFsKGF1dGgsIGF1dGhDcmVkZW50aWFsKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGphdmFzY3JpcHRcbiAgICogYXdhaXQgc2VuZFNpZ25JbkxpbmtUb0VtYWlsKGF1dGgsIGVtYWlsKTtcbiAgICogLy8gT2J0YWluIGVtYWlsTGluayBmcm9tIHVzZXIuXG4gICAqIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgc2lnbkluV2l0aEVtYWlsTGluayhhdXRoLCBlbWFpbCwgZW1haWxMaW5rKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZSB1c2VkIHRvIHZlcmlmeSB0aGUgbGluay5cbiAgICogQHBhcmFtIGVtYWlsIC0gRW1haWwgYWRkcmVzcy5cbiAgICogQHBhcmFtIGVtYWlsTGluayAtIFNpZ24taW4gZW1haWwgbGluay5cbiAgICogQHJldHVybnMgLSBUaGUgYXV0aCBwcm92aWRlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxXaXRoTGluayhcbiAgICBlbWFpbDogc3RyaW5nLFxuICAgIGVtYWlsTGluazogc3RyaW5nXG4gICk6IEVtYWlsQXV0aENyZWRlbnRpYWwge1xuICAgIGNvbnN0IGFjdGlvbkNvZGVVcmwgPSBBY3Rpb25Db2RlVVJMLnBhcnNlTGluayhlbWFpbExpbmspO1xuICAgIF9hc3NlcnQoYWN0aW9uQ29kZVVybCwgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUik7XG5cbiAgICByZXR1cm4gRW1haWxBdXRoQ3JlZGVudGlhbC5fZnJvbUVtYWlsQW5kQ29kZShcbiAgICAgIGVtYWlsLFxuICAgICAgYWN0aW9uQ29kZVVybC5jb2RlLFxuICAgICAgYWN0aW9uQ29kZVVybC50ZW5hbnRJZFxuICAgICk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoUHJvdmlkZXIgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG4vKipcbiAqIE1hcCBvZiBPQXV0aCBDdXN0b20gUGFyYW1ldGVycy5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCB0eXBlIEN1c3RvbVBhcmFtZXRlcnMgPSBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuXG4vKipcbiAqIFRoZSBiYXNlIGNsYXNzIGZvciBhbGwgRmVkZXJhdGVkIHByb3ZpZGVycyAoT0F1dGggKGluY2x1ZGluZyBPSURDKSwgU0FNTCkuXG4gKlxuICogVGhpcyBjbGFzcyBpcyBub3QgbWVhbnQgdG8gYmUgaW5zdGFudGlhdGVkIGRpcmVjdGx5LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEZlZGVyYXRlZEF1dGhQcm92aWRlciBpbXBsZW1lbnRzIEF1dGhQcm92aWRlciB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgZGVmYXVsdExhbmd1YWdlQ29kZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBjdXN0b21QYXJhbWV0ZXJzOiBDdXN0b21QYXJhbWV0ZXJzID0ge307XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yIGZvciBnZW5lcmljIE9BdXRoIHByb3ZpZGVycy5cbiAgICpcbiAgICogQHBhcmFtIHByb3ZpZGVySWQgLSBQcm92aWRlciBmb3Igd2hpY2ggY3JlZGVudGlhbHMgc2hvdWxkIGJlIGdlbmVyYXRlZC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHByb3ZpZGVySWQ6IHN0cmluZykge31cblxuICAvKipcbiAgICogU2V0IHRoZSBsYW5ndWFnZSBnb2RlLlxuICAgKlxuICAgKiBAcGFyYW0gbGFuZ3VhZ2VDb2RlIC0gbGFuZ3VhZ2UgY29kZVxuICAgKi9cbiAgc2V0RGVmYXVsdExhbmd1YWdlKGxhbmd1YWdlQ29kZTogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuZGVmYXVsdExhbmd1YWdlQ29kZSA9IGxhbmd1YWdlQ29kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBPQXV0aCBjdXN0b20gcGFyYW1ldGVycyB0byBwYXNzIGluIGFuIE9BdXRoIHJlcXVlc3QgZm9yIHBvcHVwIGFuZCByZWRpcmVjdCBzaWduLWluXG4gICAqIG9wZXJhdGlvbnMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIEZvciBhIGRldGFpbGVkIGxpc3QsIGNoZWNrIHRoZSByZXNlcnZlZCByZXF1aXJlZCBPQXV0aCAyLjAgcGFyYW1ldGVycyBzdWNoIGFzIGBjbGllbnRfaWRgLFxuICAgKiBgcmVkaXJlY3RfdXJpYCwgYHNjb3BlYCwgYHJlc3BvbnNlX3R5cGVgLCBhbmQgYHN0YXRlYCBhcmUgbm90IGFsbG93ZWQgYW5kIHdpbGwgYmUgaWdub3JlZC5cbiAgICpcbiAgICogQHBhcmFtIGN1c3RvbU9BdXRoUGFyYW1ldGVycyAtIFRoZSBjdXN0b20gT0F1dGggcGFyYW1ldGVycyB0byBwYXNzIGluIHRoZSBPQXV0aCByZXF1ZXN0LlxuICAgKi9cbiAgc2V0Q3VzdG9tUGFyYW1ldGVycyhjdXN0b21PQXV0aFBhcmFtZXRlcnM6IEN1c3RvbVBhcmFtZXRlcnMpOiBBdXRoUHJvdmlkZXIge1xuICAgIHRoaXMuY3VzdG9tUGFyYW1ldGVycyA9IGN1c3RvbU9BdXRoUGFyYW1ldGVycztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZSB0aGUgY3VycmVudCBsaXN0IG9mIHtAbGluayBDdXN0b21QYXJhbWV0ZXJzfS5cbiAgICovXG4gIGdldEN1c3RvbVBhcmFtZXRlcnMoKTogQ3VzdG9tUGFyYW1ldGVycyB7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tUGFyYW1ldGVycztcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEF1dGhQcm92aWRlciwgVXNlckNyZWRlbnRpYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQgeyBfYXNzZXJ0IH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbmltcG9ydCB7IE9BdXRoQ3JlZGVudGlhbCwgT0F1dGhDcmVkZW50aWFsUGFyYW1zIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvb2F1dGgnO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgU2lnbkluV2l0aElkcFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vLi4vaW50ZXJuYWwnO1xuaW1wb3J0IHsgRmVkZXJhdGVkQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi9mZWRlcmF0ZWQnO1xuXG4vKipcbiAqIERlZmluZXMgdGhlIG9wdGlvbnMgZm9yIGluaXRpYWxpemluZyBhbiB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAcmVtYXJrc1xuICogRm9yIElEIHRva2VucyB3aXRoIG5vbmNlIGNsYWltLCB0aGUgcmF3IG5vbmNlIGhhcyB0byBhbHNvIGJlIHByb3ZpZGVkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPQXV0aENyZWRlbnRpYWxPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBPQXV0aCBJRCB0b2tlbiB1c2VkIHRvIGluaXRpYWxpemUgdGhlIHtAbGluayBPQXV0aENyZWRlbnRpYWx9LlxuICAgKi9cbiAgaWRUb2tlbj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBPQXV0aCBhY2Nlc3MgdG9rZW4gdXNlZCB0byBpbml0aWFsaXplIHRoZSB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfS5cbiAgICovXG4gIGFjY2Vzc1Rva2VuPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHJhdyBub25jZSBhc3NvY2lhdGVkIHdpdGggdGhlIElEIHRva2VuLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBJdCBpcyByZXF1aXJlZCB3aGVuIGFuIElEIHRva2VuIHdpdGggYSBub25jZSBmaWVsZCBpcyBwcm92aWRlZC4gVGhlIFNIQS0yNTYgaGFzaCBvZiB0aGVcbiAgICogcmF3IG5vbmNlIG11c3QgbWF0Y2ggdGhlIG5vbmNlIGZpZWxkIGluIHRoZSBJRCB0b2tlbi5cbiAgICovXG4gIHJhd05vbmNlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbW1vbiBjb2RlIHRvIGFsbCBPQXV0aCBwcm92aWRlcnMuIFRoaXMgaXMgc2VwYXJhdGUgZnJvbSB0aGVcbiAqIHtAbGluayBPQXV0aFByb3ZpZGVyfSBzbyB0aGF0IGNoaWxkIHByb3ZpZGVycyAobGlrZVxuICoge0BsaW5rIEdvb2dsZUF1dGhQcm92aWRlcn0pIGRvbid0IGluaGVyaXQgdGhlIGBjcmVkZW50aWFsYCBpbnN0YW5jZSBtZXRob2QuXG4gKiBJbnN0ZWFkLCB0aGV5IHJlbHkgb24gYSBzdGF0aWMgYGNyZWRlbnRpYWxgIG1ldGhvZC5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VPQXV0aFByb3ZpZGVyXG4gIGV4dGVuZHMgRmVkZXJhdGVkQXV0aFByb3ZpZGVyXG4gIGltcGxlbWVudHMgQXV0aFByb3ZpZGVyXG57XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBzY29wZXM6IHN0cmluZ1tdID0gW107XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBPQXV0aCBzY29wZSB0byB0aGUgY3JlZGVudGlhbC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gUHJvdmlkZXIgT0F1dGggc2NvcGUgdG8gYWRkLlxuICAgKi9cbiAgYWRkU2NvcGUoc2NvcGU6IHN0cmluZyk6IEF1dGhQcm92aWRlciB7XG4gICAgLy8gSWYgbm90IGFscmVhZHkgYWRkZWQsIGFkZCBzY29wZSB0byBsaXN0LlxuICAgIGlmICghdGhpcy5zY29wZXMuaW5jbHVkZXMoc2NvcGUpKSB7XG4gICAgICB0aGlzLnNjb3Blcy5wdXNoKHNjb3BlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgdGhlIGN1cnJlbnQgbGlzdCBvZiBPQXV0aCBzY29wZXMuXG4gICAqL1xuICBnZXRTY29wZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5zY29wZXNdO1xuICB9XG59XG5cbi8qKlxuICogUHJvdmlkZXIgZm9yIGdlbmVyYXRpbmcgZ2VuZXJpYyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHJlZGlyZWN0LlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgT0F1dGhQcm92aWRlcignZ29vZ2xlLmNvbScpO1xuICogLy8gU3RhcnQgYSBzaWduIGluIHByb2Nlc3MgZm9yIGFuIHVuYXV0aGVudGljYXRlZCB1c2VyLlxuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdlbWFpbCcpO1xuICogYXdhaXQgc2lnbkluV2l0aFJlZGlyZWN0KGF1dGgsIHByb3ZpZGVyKTtcbiAqIC8vIFRoaXMgd2lsbCB0cmlnZ2VyIGEgZnVsbCBwYWdlIHJlZGlyZWN0IGF3YXkgZnJvbSB5b3VyIGFwcFxuICpcbiAqIC8vIEFmdGVyIHJldHVybmluZyBmcm9tIHRoZSByZWRpcmVjdCB3aGVuIHlvdXIgYXBwIGluaXRpYWxpemVzIHlvdSBjYW4gb2J0YWluIHRoZSByZXN1bHRcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldFJlZGlyZWN0UmVzdWx0KGF1dGgpO1xuICogaWYgKHJlc3VsdCkge1xuICogICAvLyBUaGlzIGlzIHRoZSBzaWduZWQtaW4gdXNlclxuICogICBjb25zdCB1c2VyID0gcmVzdWx0LnVzZXI7XG4gKiAgIC8vIFRoaXMgZ2l2ZXMgeW91IGEgT0F1dGggQWNjZXNzIFRva2VuIGZvciB0aGUgcHJvdmlkZXIuXG4gKiAgIGNvbnN0IGNyZWRlbnRpYWwgPSBwcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChhdXRoLCByZXN1bHQpO1xuICogICBjb25zdCB0b2tlbiA9IGNyZWRlbnRpYWwuYWNjZXNzVG9rZW47XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHBvcHVwLlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgT0F1dGhQcm92aWRlcignZ29vZ2xlLmNvbScpO1xuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdlbWFpbCcpO1xuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgc2lnbkluV2l0aFBvcHVwKGF1dGgsIHByb3ZpZGVyKTtcbiAqXG4gKiAvLyBUaGUgc2lnbmVkLWluIHVzZXIgaW5mby5cbiAqIGNvbnN0IHVzZXIgPSByZXN1bHQudXNlcjtcbiAqIC8vIFRoaXMgZ2l2ZXMgeW91IGEgT0F1dGggQWNjZXNzIFRva2VuIGZvciB0aGUgcHJvdmlkZXIuXG4gKiBjb25zdCBjcmVkZW50aWFsID0gcHJvdmlkZXIuY3JlZGVudGlhbEZyb21SZXN1bHQoYXV0aCwgcmVzdWx0KTtcbiAqIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqIGBgYFxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgT0F1dGhQcm92aWRlciBleHRlbmRzIEJhc2VPQXV0aFByb3ZpZGVyIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4ge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIEpTT04gc3RyaW5nIG9yIGEgcGxhaW4gb2JqZWN0LlxuICAgKiBAcGFyYW0ganNvbiAtIEEgcGxhaW4gb2JqZWN0IG9yIGEgSlNPTiBzdHJpbmdcbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbUpTT04oanNvbjogb2JqZWN0IHwgc3RyaW5nKTogT0F1dGhDcmVkZW50aWFsIHtcbiAgICBjb25zdCBvYmogPSB0eXBlb2YganNvbiA9PT0gJ3N0cmluZycgPyBKU09OLnBhcnNlKGpzb24pIDoganNvbjtcbiAgICBfYXNzZXJ0KFxuICAgICAgJ3Byb3ZpZGVySWQnIGluIG9iaiAmJiAnc2lnbkluTWV0aG9kJyBpbiBvYmosXG4gICAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICAgKTtcbiAgICByZXR1cm4gT0F1dGhDcmVkZW50aWFsLl9mcm9tUGFyYW1zKG9iaik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSBnZW5lcmljIE9BdXRoIHByb3ZpZGVyJ3MgYWNjZXNzIHRva2VuIG9yIElEIHRva2VuLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBUaGUgcmF3IG5vbmNlIGlzIHJlcXVpcmVkIHdoZW4gYW4gSUQgdG9rZW4gd2l0aCBhIG5vbmNlIGZpZWxkIGlzIHByb3ZpZGVkLiBUaGUgU0hBLTI1NiBoYXNoIG9mXG4gICAqIHRoZSByYXcgbm9uY2UgbXVzdCBtYXRjaCB0aGUgbm9uY2UgZmllbGQgaW4gdGhlIElEIHRva2VuLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqYXZhc2NyaXB0XG4gICAqIC8vIGBnb29nbGVVc2VyYCBmcm9tIHRoZSBvbnN1Y2Nlc3MgR29vZ2xlIFNpZ24gSW4gY2FsbGJhY2suXG4gICAqIC8vIEluaXRpYWxpemUgYSBnZW5lcmF0ZSBPQXV0aCBwcm92aWRlciB3aXRoIGEgYGdvb2dsZS5jb21gIHByb3ZpZGVySWQuXG4gICAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IE9BdXRoUHJvdmlkZXIoJ2dvb2dsZS5jb20nKTtcbiAgICogY29uc3QgY3JlZGVudGlhbCA9IHByb3ZpZGVyLmNyZWRlbnRpYWwoe1xuICAgKiAgIGlkVG9rZW46IGdvb2dsZVVzZXIuZ2V0QXV0aFJlc3BvbnNlKCkuaWRfdG9rZW4sXG4gICAqIH0pO1xuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoQ3JlZGVudGlhbChjcmVkZW50aWFsKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBFaXRoZXIgdGhlIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIElEIHRva2VuLCBhY2Nlc3MgdG9rZW4gYW5kIHJhdyBub25jZVxuICAgKiBvciB0aGUgSUQgdG9rZW4gc3RyaW5nLlxuICAgKi9cbiAgY3JlZGVudGlhbChwYXJhbXM6IE9BdXRoQ3JlZGVudGlhbE9wdGlvbnMpOiBPQXV0aENyZWRlbnRpYWwge1xuICAgIHJldHVybiB0aGlzLl9jcmVkZW50aWFsKHsgLi4ucGFyYW1zLCBub25jZTogcGFyYW1zLnJhd05vbmNlIH0pO1xuICB9XG5cbiAgLyoqIEFuIGludGVybmFsIGNyZWRlbnRpYWwgbWV0aG9kIHRoYXQgYWNjZXB0cyBtb3JlIHBlcm1pc3NpdmUgb3B0aW9ucyAqL1xuICBwcml2YXRlIF9jcmVkZW50aWFsKFxuICAgIHBhcmFtczogT21pdDxPQXV0aENyZWRlbnRpYWxQYXJhbXMsICdzaWduSW5NZXRob2QnIHwgJ3Byb3ZpZGVySWQnPlxuICApOiBPQXV0aENyZWRlbnRpYWwge1xuICAgIF9hc3NlcnQocGFyYW1zLmlkVG9rZW4gfHwgcGFyYW1zLmFjY2Vzc1Rva2VuLCBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SKTtcbiAgICAvLyBGb3IgT0F1dGhDcmVkZW50aWFsLCBzaWduIGluIG1ldGhvZCBpcyBzYW1lIGFzIHByb3ZpZGVySWQuXG4gICAgcmV0dXJuIE9BdXRoQ3JlZGVudGlhbC5fZnJvbVBhcmFtcyh7XG4gICAgICAuLi5wYXJhbXMsXG4gICAgICBwcm92aWRlcklkOiB0aGlzLnByb3ZpZGVySWQsXG4gICAgICBzaWduSW5NZXRob2Q6IHRoaXMucHJvdmlkZXJJZFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXh0cmFjdCB0aGUgdW5kZXJseWluZyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmcm9tIGEge0BsaW5rIFVzZXJDcmVkZW50aWFsfS5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbVJlc3VsdChcbiAgICB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWxcbiAgKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIE9BdXRoUHJvdmlkZXIub2F1dGhDcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIHVzZXJDcmVkZW50aWFsIGFzIFVzZXJDcmVkZW50aWFsSW50ZXJuYWxcbiAgICApO1xuICB9XG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBBdXRoRXJyb3J9IHdoaWNoIHdhc1xuICAgKiB0aHJvd24gZHVyaW5nIGEgc2lnbi1pbiwgbGluaywgb3IgcmVhdXRoZW50aWNhdGUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tRXJyb3IoZXJyb3I6IEZpcmViYXNlRXJyb3IpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gT0F1dGhQcm92aWRlci5vYXV0aENyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIG9hdXRoQ3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3Qoe1xuICAgIF90b2tlblJlc3BvbnNlOiB0b2tlblJlc3BvbnNlXG4gIH06IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgaWYgKCF0b2tlblJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICBvYXV0aElkVG9rZW4sXG4gICAgICBvYXV0aEFjY2Vzc1Rva2VuLFxuICAgICAgb2F1dGhUb2tlblNlY3JldCxcbiAgICAgIHBlbmRpbmdUb2tlbixcbiAgICAgIG5vbmNlLFxuICAgICAgcHJvdmlkZXJJZFxuICAgIH0gPSB0b2tlblJlc3BvbnNlIGFzIFNpZ25JbldpdGhJZHBSZXNwb25zZTtcbiAgICBpZiAoXG4gICAgICAhb2F1dGhBY2Nlc3NUb2tlbiAmJlxuICAgICAgIW9hdXRoVG9rZW5TZWNyZXQgJiZcbiAgICAgICFvYXV0aElkVG9rZW4gJiZcbiAgICAgICFwZW5kaW5nVG9rZW5cbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmICghcHJvdmlkZXJJZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBuZXcgT0F1dGhQcm92aWRlcihwcm92aWRlcklkKS5fY3JlZGVudGlhbCh7XG4gICAgICAgIGlkVG9rZW46IG9hdXRoSWRUb2tlbixcbiAgICAgICAgYWNjZXNzVG9rZW46IG9hdXRoQWNjZXNzVG9rZW4sXG4gICAgICAgIG5vbmNlLFxuICAgICAgICBwZW5kaW5nVG9rZW5cbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IEZpcmViYXNlRXJyb3IgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5cbmltcG9ydCB7IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgT0F1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvb2F1dGgnO1xuaW1wb3J0IHsgQmFzZU9BdXRoUHJvdmlkZXIgfSBmcm9tICcuL29hdXRoJztcbmltcG9ydCB7IFByb3ZpZGVySWQsIFNpZ25Jbk1ldGhvZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuLyoqXG4gKiBQcm92aWRlciBmb3IgZ2VuZXJhdGluZyBhbiB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmb3Ige0BsaW5rIFByb3ZpZGVySWR9LkZBQ0VCT09LLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcmVkaXJlY3QuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBGYWNlYm9va0F1dGhQcm92aWRlcigpO1xuICogLy8gU3RhcnQgYSBzaWduIGluIHByb2Nlc3MgZm9yIGFuIHVuYXV0aGVudGljYXRlZCB1c2VyLlxuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3VzZXJfYmlydGhkYXknKTtcbiAqIGF3YWl0IHNpZ25JbldpdGhSZWRpcmVjdChhdXRoLCBwcm92aWRlcik7XG4gKiAvLyBUaGlzIHdpbGwgdHJpZ2dlciBhIGZ1bGwgcGFnZSByZWRpcmVjdCBhd2F5IGZyb20geW91ciBhcHBcbiAqXG4gKiAvLyBBZnRlciByZXR1cm5pbmcgZnJvbSB0aGUgcmVkaXJlY3Qgd2hlbiB5b3VyIGFwcCBpbml0aWFsaXplcyB5b3UgY2FuIG9idGFpbiB0aGUgcmVzdWx0XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRSZWRpcmVjdFJlc3VsdChhdXRoKTtcbiAqIGlmIChyZXN1bHQpIHtcbiAqICAgLy8gVGhpcyBpcyB0aGUgc2lnbmVkLWluIHVzZXJcbiAqICAgY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogICAvLyBUaGlzIGdpdmVzIHlvdSBhIEZhY2Vib29rIEFjY2VzcyBUb2tlbi5cbiAqICAgY29uc3QgY3JlZGVudGlhbCA9IEZhY2Vib29rQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiAgIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcG9wdXAuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBGYWNlYm9va0F1dGhQcm92aWRlcigpO1xuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3VzZXJfYmlydGhkYXknKTtcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNpZ25JbldpdGhQb3B1cChhdXRoLCBwcm92aWRlcik7XG4gKlxuICogLy8gVGhlIHNpZ25lZC1pbiB1c2VyIGluZm8uXG4gKiBjb25zdCB1c2VyID0gcmVzdWx0LnVzZXI7XG4gKiAvLyBUaGlzIGdpdmVzIHlvdSBhIEZhY2Vib29rIEFjY2VzcyBUb2tlbi5cbiAqIGNvbnN0IGNyZWRlbnRpYWwgPSBGYWNlYm9va0F1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogY29uc3QgdG9rZW4gPSBjcmVkZW50aWFsLmFjY2Vzc1Rva2VuO1xuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgRmFjZWJvb2tBdXRoUHJvdmlkZXIgZXh0ZW5kcyBCYXNlT0F1dGhQcm92aWRlciB7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkZBQ0VCT09LLiAqL1xuICBzdGF0aWMgcmVhZG9ubHkgRkFDRUJPT0tfU0lHTl9JTl9NRVRIT0Q6ICdmYWNlYm9vay5jb20nID1cbiAgICBTaWduSW5NZXRob2QuRkFDRUJPT0s7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5GQUNFQk9PSy4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IFBST1ZJREVSX0lEOiAnZmFjZWJvb2suY29tJyA9IFByb3ZpZGVySWQuRkFDRUJPT0s7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoUHJvdmlkZXJJZC5GQUNFQk9PSyk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGNyZWRlbnRpYWwgZm9yIEZhY2Vib29rLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGBqYXZhc2NyaXB0XG4gICAqIC8vIGBldmVudGAgZnJvbSB0aGUgRmFjZWJvb2sgYXV0aC5hdXRoUmVzcG9uc2VDaGFuZ2UgY2FsbGJhY2suXG4gICAqIGNvbnN0IGNyZWRlbnRpYWwgPSBGYWNlYm9va0F1dGhQcm92aWRlci5jcmVkZW50aWFsKGV2ZW50LmF1dGhSZXNwb25zZS5hY2Nlc3NUb2tlbik7XG4gICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNpZ25JbldpdGhDcmVkZW50aWFsKGNyZWRlbnRpYWwpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIGFjY2Vzc1Rva2VuIC0gRmFjZWJvb2sgYWNjZXNzIHRva2VuLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWwoYWNjZXNzVG9rZW46IHN0cmluZyk6IE9BdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIE9BdXRoQ3JlZGVudGlhbC5fZnJvbVBhcmFtcyh7XG4gICAgICBwcm92aWRlcklkOiBGYWNlYm9va0F1dGhQcm92aWRlci5QUk9WSURFUl9JRCxcbiAgICAgIHNpZ25Jbk1ldGhvZDogRmFjZWJvb2tBdXRoUHJvdmlkZXIuRkFDRUJPT0tfU0lHTl9JTl9NRVRIT0QsXG4gICAgICBhY2Nlc3NUb2tlblxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXh0cmFjdCB0aGUgdW5kZXJseWluZyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmcm9tIGEge0BsaW5rIFVzZXJDcmVkZW50aWFsfS5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbVJlc3VsdChcbiAgICB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWxcbiAgKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIEZhY2Vib29rQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgdXNlckNyZWRlbnRpYWwgYXMgVXNlckNyZWRlbnRpYWxJbnRlcm5hbFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSB7QGxpbmsgQXV0aEVycm9yfSB3aGljaCB3YXNcbiAgICogdGhyb3duIGR1cmluZyBhIHNpZ24taW4sIGxpbmssIG9yIHJlYXV0aGVudGljYXRlIG9wZXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbUVycm9yKGVycm9yOiBGaXJlYmFzZUVycm9yKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIEZhY2Vib29rQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KHtcbiAgICBfdG9rZW5SZXNwb25zZTogdG9rZW5SZXNwb25zZVxuICB9OiBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGlmICghdG9rZW5SZXNwb25zZSB8fCAhKCdvYXV0aEFjY2Vzc1Rva2VuJyBpbiB0b2tlblJlc3BvbnNlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlblJlc3BvbnNlLm9hdXRoQWNjZXNzVG9rZW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gRmFjZWJvb2tBdXRoUHJvdmlkZXIuY3JlZGVudGlhbCh0b2tlblJlc3BvbnNlLm9hdXRoQWNjZXNzVG9rZW4pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgU2lnbkluV2l0aElkcFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2lkcCc7XG5pbXBvcnQgeyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IE9BdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4uL2NyZWRlbnRpYWxzL29hdXRoJztcbmltcG9ydCB7IEJhc2VPQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi9vYXV0aCc7XG5pbXBvcnQgeyBQcm92aWRlcklkLCBTaWduSW5NZXRob2QgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5cbi8qKlxuICogUHJvdmlkZXIgZm9yIGdlbmVyYXRpbmcgYW4ge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZm9yIHtAbGluayBQcm92aWRlcklkfS5HT09HTEUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIC8vIFNpZ24gaW4gdXNpbmcgYSByZWRpcmVjdC5cbiAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IEdvb2dsZUF1dGhQcm92aWRlcigpO1xuICogLy8gU3RhcnQgYSBzaWduIGluIHByb2Nlc3MgZm9yIGFuIHVuYXV0aGVudGljYXRlZCB1c2VyLlxuICogcHJvdmlkZXIuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdlbWFpbCcpO1xuICogYXdhaXQgc2lnbkluV2l0aFJlZGlyZWN0KGF1dGgsIHByb3ZpZGVyKTtcbiAqIC8vIFRoaXMgd2lsbCB0cmlnZ2VyIGEgZnVsbCBwYWdlIHJlZGlyZWN0IGF3YXkgZnJvbSB5b3VyIGFwcFxuICpcbiAqIC8vIEFmdGVyIHJldHVybmluZyBmcm9tIHRoZSByZWRpcmVjdCB3aGVuIHlvdXIgYXBwIGluaXRpYWxpemVzIHlvdSBjYW4gb2J0YWluIHRoZSByZXN1bHRcbiAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldFJlZGlyZWN0UmVzdWx0KGF1dGgpO1xuICogaWYgKHJlc3VsdCkge1xuICogICAvLyBUaGlzIGlzIHRoZSBzaWduZWQtaW4gdXNlclxuICogICBjb25zdCB1c2VyID0gcmVzdWx0LnVzZXI7XG4gKiAgIC8vIFRoaXMgZ2l2ZXMgeW91IGEgR29vZ2xlIEFjY2VzcyBUb2tlbi5cbiAqICAgY29uc3QgY3JlZGVudGlhbCA9IEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogICBjb25zdCB0b2tlbiA9IGNyZWRlbnRpYWwuYWNjZXNzVG9rZW47XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHBvcHVwLlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgR29vZ2xlQXV0aFByb3ZpZGVyKCk7XG4gKiBwcm92aWRlci5hZGRTY29wZSgncHJvZmlsZScpO1xuICogcHJvdmlkZXIuYWRkU2NvcGUoJ2VtYWlsJyk7XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoUG9wdXAoYXV0aCwgcHJvdmlkZXIpO1xuICpcbiAqIC8vIFRoZSBzaWduZWQtaW4gdXNlciBpbmZvLlxuICogY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogLy8gVGhpcyBnaXZlcyB5b3UgYSBHb29nbGUgQWNjZXNzIFRva2VuLlxuICogY29uc3QgY3JlZGVudGlhbCA9IEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogY29uc3QgdG9rZW4gPSBjcmVkZW50aWFsLmFjY2Vzc1Rva2VuO1xuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgR29vZ2xlQXV0aFByb3ZpZGVyIGV4dGVuZHMgQmFzZU9BdXRoUHJvdmlkZXIge1xuICAvKiogQWx3YXlzIHNldCB0byB7QGxpbmsgU2lnbkluTWV0aG9kfS5HT09HTEUuICovXG4gIHN0YXRpYyByZWFkb25seSBHT09HTEVfU0lHTl9JTl9NRVRIT0Q6ICdnb29nbGUuY29tJyA9IFNpZ25Jbk1ldGhvZC5HT09HTEU7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5HT09HTEUuICovXG4gIHN0YXRpYyByZWFkb25seSBQUk9WSURFUl9JRDogJ2dvb2dsZS5jb20nID0gUHJvdmlkZXJJZC5HT09HTEU7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoUHJvdmlkZXJJZC5HT09HTEUpO1xuICAgIHRoaXMuYWRkU2NvcGUoJ3Byb2ZpbGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY3JlZGVudGlhbCBmb3IgR29vZ2xlLiBBdCBsZWFzdCBvbmUgb2YgSUQgdG9rZW4gYW5kIGFjY2VzcyB0b2tlbiBpcyByZXF1aXJlZC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgamF2YXNjcmlwdFxuICAgKiAvLyBcXGBnb29nbGVVc2VyXFxgIGZyb20gdGhlIG9uc3VjY2VzcyBHb29nbGUgU2lnbiBJbiBjYWxsYmFjay5cbiAgICogY29uc3QgY3JlZGVudGlhbCA9IEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsKGdvb2dsZVVzZXIuZ2V0QXV0aFJlc3BvbnNlKCkuaWRfdG9rZW4pO1xuICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoQ3JlZGVudGlhbChjcmVkZW50aWFsKTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBpZFRva2VuIC0gR29vZ2xlIElEIHRva2VuLlxuICAgKiBAcGFyYW0gYWNjZXNzVG9rZW4gLSBHb29nbGUgYWNjZXNzIHRva2VuLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWwoXG4gICAgaWRUb2tlbj86IHN0cmluZyB8IG51bGwsXG4gICAgYWNjZXNzVG9rZW4/OiBzdHJpbmcgfCBudWxsXG4gICk6IE9BdXRoQ3JlZGVudGlhbCB7XG4gICAgcmV0dXJuIE9BdXRoQ3JlZGVudGlhbC5fZnJvbVBhcmFtcyh7XG4gICAgICBwcm92aWRlcklkOiBHb29nbGVBdXRoUHJvdmlkZXIuUFJPVklERVJfSUQsXG4gICAgICBzaWduSW5NZXRob2Q6IEdvb2dsZUF1dGhQcm92aWRlci5HT09HTEVfU0lHTl9JTl9NRVRIT0QsXG4gICAgICBpZFRva2VuLFxuICAgICAgYWNjZXNzVG9rZW5cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBVc2VyQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyQ3JlZGVudGlhbCAtIFRoZSB1c2VyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21SZXN1bHQoXG4gICAgdXNlckNyZWRlbnRpYWw6IFVzZXJDcmVkZW50aWFsXG4gICk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBHb29nbGVBdXRoUHJvdmlkZXIuY3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3QoXG4gICAgICB1c2VyQ3JlZGVudGlhbCBhcyBVc2VyQ3JlZGVudGlhbEludGVybmFsXG4gICAgKTtcbiAgfVxuICAvKipcbiAgICogVXNlZCB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSB7QGxpbmsgQXV0aEVycm9yfSB3aGljaCB3YXNcbiAgICogdGhyb3duIGR1cmluZyBhIHNpZ24taW4sIGxpbmssIG9yIHJlYXV0aGVudGljYXRlIG9wZXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbUVycm9yKGVycm9yOiBGaXJlYmFzZUVycm9yKTogT0F1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgcmV0dXJuIEdvb2dsZUF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIChlcnJvci5jdXN0b21EYXRhIHx8IHt9KSBhcyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBjcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdCh7XG4gICAgX3Rva2VuUmVzcG9uc2U6IHRva2VuUmVzcG9uc2VcbiAgfTogVGFnZ2VkV2l0aFRva2VuUmVzcG9uc2UpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICBpZiAoIXRva2VuUmVzcG9uc2UpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHsgb2F1dGhJZFRva2VuLCBvYXV0aEFjY2Vzc1Rva2VuIH0gPVxuICAgICAgdG9rZW5SZXNwb25zZSBhcyBTaWduSW5XaXRoSWRwUmVzcG9uc2U7XG4gICAgaWYgKCFvYXV0aElkVG9rZW4gJiYgIW9hdXRoQWNjZXNzVG9rZW4pIHtcbiAgICAgIC8vIFRoaXMgY291bGQgYmUgYW4gb2F1dGggMSBjcmVkZW50aWFsIG9yIGEgcGhvbmUgY3JlZGVudGlhbFxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBHb29nbGVBdXRoUHJvdmlkZXIuY3JlZGVudGlhbChvYXV0aElkVG9rZW4sIG9hdXRoQWNjZXNzVG9rZW4pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgRmlyZWJhc2VFcnJvciB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuaW1wb3J0IHsgVGFnZ2VkV2l0aFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBPQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuLi9jcmVkZW50aWFscy9vYXV0aCc7XG5pbXBvcnQgeyBCYXNlT0F1dGhQcm92aWRlciB9IGZyb20gJy4vb2F1dGgnO1xuaW1wb3J0IHsgUHJvdmlkZXJJZCwgU2lnbkluTWV0aG9kIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBnZW5lcmF0aW5nIGFuIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZvciB7QGxpbmsgUHJvdmlkZXJJZH0uR0lUSFVCLlxuICpcbiAqIEByZW1hcmtzXG4gKiBHaXRIdWIgcmVxdWlyZXMgYW4gT0F1dGggMi4wIHJlZGlyZWN0LCBzbyB5b3UgY2FuIGVpdGhlciBoYW5kbGUgdGhlIHJlZGlyZWN0IGRpcmVjdGx5LCBvciB1c2VcbiAqIHRoZSB7QGxpbmsgc2lnbkluV2l0aFBvcHVwfSBoYW5kbGVyOlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcmVkaXJlY3QuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBHaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAqIC8vIFN0YXJ0IGEgc2lnbiBpbiBwcm9jZXNzIGZvciBhbiB1bmF1dGhlbnRpY2F0ZWQgdXNlci5cbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdyZXBvJyk7XG4gKiBhd2FpdCBzaWduSW5XaXRoUmVkaXJlY3QoYXV0aCwgcHJvdmlkZXIpO1xuICogLy8gVGhpcyB3aWxsIHRyaWdnZXIgYSBmdWxsIHBhZ2UgcmVkaXJlY3QgYXdheSBmcm9tIHlvdXIgYXBwXG4gKlxuICogLy8gQWZ0ZXIgcmV0dXJuaW5nIGZyb20gdGhlIHJlZGlyZWN0IHdoZW4geW91ciBhcHAgaW5pdGlhbGl6ZXMgeW91IGNhbiBvYnRhaW4gdGhlIHJlc3VsdFxuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2V0UmVkaXJlY3RSZXN1bHQoYXV0aCk7XG4gKiBpZiAocmVzdWx0KSB7XG4gKiAgIC8vIFRoaXMgaXMgdGhlIHNpZ25lZC1pbiB1c2VyXG4gKiAgIGNvbnN0IHVzZXIgPSByZXN1bHQudXNlcjtcbiAqICAgLy8gVGhpcyBnaXZlcyB5b3UgYSBHaXRIdWIgQWNjZXNzIFRva2VuLlxuICogICBjb25zdCBjcmVkZW50aWFsID0gR2l0aHViQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiAgIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBTaWduIGluIHVzaW5nIGEgcG9wdXAuXG4gKiBjb25zdCBwcm92aWRlciA9IG5ldyBHaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAqIHByb3ZpZGVyLmFkZFNjb3BlKCdyZXBvJyk7XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBzaWduSW5XaXRoUG9wdXAoYXV0aCwgcHJvdmlkZXIpO1xuICpcbiAqIC8vIFRoZSBzaWduZWQtaW4gdXNlciBpbmZvLlxuICogY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogLy8gVGhpcyBnaXZlcyB5b3UgYSBHaXRIdWIgQWNjZXNzIFRva2VuLlxuICogY29uc3QgY3JlZGVudGlhbCA9IEdpdGh1YkF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVJlc3VsdChyZXN1bHQpO1xuICogY29uc3QgdG9rZW4gPSBjcmVkZW50aWFsLmFjY2Vzc1Rva2VuO1xuICogYGBgXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBHaXRodWJBdXRoUHJvdmlkZXIgZXh0ZW5kcyBCYXNlT0F1dGhQcm92aWRlciB7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LkdJVEhVQi4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IEdJVEhVQl9TSUdOX0lOX01FVEhPRDogJ2dpdGh1Yi5jb20nID0gU2lnbkluTWV0aG9kLkdJVEhVQjtcbiAgLyoqIEFsd2F5cyBzZXQgdG8ge0BsaW5rIFByb3ZpZGVySWR9LkdJVEhVQi4gKi9cbiAgc3RhdGljIHJlYWRvbmx5IFBST1ZJREVSX0lEOiAnZ2l0aHViLmNvbScgPSBQcm92aWRlcklkLkdJVEhVQjtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihQcm92aWRlcklkLkdJVEhVQik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGNyZWRlbnRpYWwgZm9yIEdpdEh1Yi5cbiAgICpcbiAgICogQHBhcmFtIGFjY2Vzc1Rva2VuIC0gR2l0SHViIGFjY2VzcyB0b2tlbi5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsKGFjY2Vzc1Rva2VuOiBzdHJpbmcpOiBPQXV0aENyZWRlbnRpYWwge1xuICAgIHJldHVybiBPQXV0aENyZWRlbnRpYWwuX2Zyb21QYXJhbXMoe1xuICAgICAgcHJvdmlkZXJJZDogR2l0aHViQXV0aFByb3ZpZGVyLlBST1ZJREVSX0lELFxuICAgICAgc2lnbkluTWV0aG9kOiBHaXRodWJBdXRoUHJvdmlkZXIuR0lUSFVCX1NJR05fSU5fTUVUSE9ELFxuICAgICAgYWNjZXNzVG9rZW5cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBVc2VyQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyQ3JlZGVudGlhbCAtIFRoZSB1c2VyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21SZXN1bHQoXG4gICAgdXNlckNyZWRlbnRpYWw6IFVzZXJDcmVkZW50aWFsXG4gICk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBHaXRodWJBdXRoUHJvdmlkZXIuY3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3QoXG4gICAgICB1c2VyQ3JlZGVudGlhbCBhcyBVc2VyQ3JlZGVudGlhbEludGVybmFsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBBdXRoRXJyb3J9IHdoaWNoIHdhc1xuICAgKiB0aHJvd24gZHVyaW5nIGEgc2lnbi1pbiwgbGluaywgb3IgcmVhdXRoZW50aWNhdGUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tRXJyb3IoZXJyb3I6IEZpcmViYXNlRXJyb3IpOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gR2l0aHViQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KHtcbiAgICBfdG9rZW5SZXNwb25zZTogdG9rZW5SZXNwb25zZVxuICB9OiBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGlmICghdG9rZW5SZXNwb25zZSB8fCAhKCdvYXV0aEFjY2Vzc1Rva2VuJyBpbiB0b2tlblJlc3BvbnNlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCF0b2tlblJlc3BvbnNlLm9hdXRoQWNjZXNzVG9rZW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gR2l0aHViQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWwodG9rZW5SZXNwb25zZS5vYXV0aEFjY2Vzc1Rva2VuKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgU0FNTCBjcmVkZW50aWFscyByZXR1cm5lZCBieSBhbiB7QGxpbmsgU0FNTEF1dGhQcm92aWRlcn0uXG4gKlxuICogQHB1YmxpY1xuICovXG5cbmltcG9ydCB7XG4gIHNpZ25JbldpdGhJZHAsXG4gIFNpZ25JbldpdGhJZHBSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9pZHAnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vYXV0aF9jcmVkZW50aWFsJztcblxuY29uc3QgSURQX1JFUVVFU1RfVVJJID0gJ2h0dHA6Ly9sb2NhbGhvc3QnO1xuXG4vKipcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFNBTUxBdXRoQ3JlZGVudGlhbCBleHRlbmRzIEF1dGhDcmVkZW50aWFsIHtcbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHByb3ZpZGVySWQ6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdUb2tlbjogc3RyaW5nXG4gICkge1xuICAgIHN1cGVyKHByb3ZpZGVySWQsIHByb3ZpZGVySWQpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuYnVpbGRSZXF1ZXN0KCk7XG4gICAgcmV0dXJuIHNpZ25JbldpdGhJZHAoYXV0aCwgcmVxdWVzdCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9saW5rVG9JZFRva2VuKFxuICAgIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBpZFRva2VuOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5idWlsZFJlcXVlc3QoKTtcbiAgICByZXF1ZXN0LmlkVG9rZW4gPSBpZFRva2VuO1xuICAgIHJldHVybiBzaWduSW5XaXRoSWRwKGF1dGgsIHJlcXVlc3QpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfZ2V0UmVhdXRoZW50aWNhdGlvblJlc29sdmVyKGF1dGg6IEF1dGhJbnRlcm5hbCk6IFByb21pc2U8SWRUb2tlblJlc3BvbnNlPiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuYnVpbGRSZXF1ZXN0KCk7XG4gICAgcmVxdWVzdC5hdXRvQ3JlYXRlID0gZmFsc2U7XG4gICAgcmV0dXJuIHNpZ25JbldpdGhJZHAoYXV0aCwgcmVxdWVzdCk7XG4gIH1cblxuICAvKioge0Bpbmhlcml0ZG9jIEF1dGhDcmVkZW50aWFsLnRvSlNPTn0gICovXG4gIHRvSlNPTigpOiBvYmplY3Qge1xuICAgIHJldHVybiB7XG4gICAgICBzaWduSW5NZXRob2Q6IHRoaXMuc2lnbkluTWV0aG9kLFxuICAgICAgcHJvdmlkZXJJZDogdGhpcy5wcm92aWRlcklkLFxuICAgICAgcGVuZGluZ1Rva2VuOiB0aGlzLnBlbmRpbmdUb2tlblxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU3RhdGljIG1ldGhvZCB0byBkZXNlcmlhbGl6ZSBhIEpTT04gcmVwcmVzZW50YXRpb24gb2YgYW4gb2JqZWN0IGludG8gYW5cbiAgICoge0BsaW5rICBBdXRoQ3JlZGVudGlhbH0uXG4gICAqXG4gICAqIEBwYXJhbSBqc29uIC0gSW5wdXQgY2FuIGJlIGVpdGhlciBPYmplY3Qgb3IgdGhlIHN0cmluZ2lmaWVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBvYmplY3QuXG4gICAqIFdoZW4gc3RyaW5nIGlzIHByb3ZpZGVkLCBKU09OLnBhcnNlIHdvdWxkIGJlIGNhbGxlZCBmaXJzdC5cbiAgICpcbiAgICogQHJldHVybnMgSWYgdGhlIEpTT04gaW5wdXQgZG9lcyBub3QgcmVwcmVzZW50IGFuIHtAbGluayAgQXV0aENyZWRlbnRpYWx9LCBudWxsIGlzIHJldHVybmVkLlxuICAgKi9cbiAgc3RhdGljIGZyb21KU09OKGpzb246IHN0cmluZyB8IG9iamVjdCk6IFNBTUxBdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGNvbnN0IG9iaiA9IHR5cGVvZiBqc29uID09PSAnc3RyaW5nJyA/IEpTT04ucGFyc2UoanNvbikgOiBqc29uO1xuICAgIGNvbnN0IHsgcHJvdmlkZXJJZCwgc2lnbkluTWV0aG9kLCBwZW5kaW5nVG9rZW4gfTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9XG4gICAgICBvYmo7XG4gICAgaWYgKFxuICAgICAgIXByb3ZpZGVySWQgfHxcbiAgICAgICFzaWduSW5NZXRob2QgfHxcbiAgICAgICFwZW5kaW5nVG9rZW4gfHxcbiAgICAgIHByb3ZpZGVySWQgIT09IHNpZ25Jbk1ldGhvZFxuICAgICkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBTQU1MQXV0aENyZWRlbnRpYWwocHJvdmlkZXJJZCwgcGVuZGluZ1Rva2VuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgc3RhdGljIG1ldGhvZCB0byBhdm9pZCBleHBvc2luZyB0aGUgY29uc3RydWN0b3IgdG8gZW5kIHVzZXJzLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHN0YXRpYyBfY3JlYXRlKHByb3ZpZGVySWQ6IHN0cmluZywgcGVuZGluZ1Rva2VuOiBzdHJpbmcpOiBTQU1MQXV0aENyZWRlbnRpYWwge1xuICAgIHJldHVybiBuZXcgU0FNTEF1dGhDcmVkZW50aWFsKHByb3ZpZGVySWQsIHBlbmRpbmdUb2tlbik7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkUmVxdWVzdCgpOiBTaWduSW5XaXRoSWRwUmVxdWVzdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlcXVlc3RVcmk6IElEUF9SRVFVRVNUX1VSSSxcbiAgICAgIHJldHVyblNlY3VyZVRva2VuOiB0cnVlLFxuICAgICAgcGVuZGluZ1Rva2VuOiB0aGlzLnBlbmRpbmdUb2tlblxuICAgIH07XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgU2lnbkluV2l0aElkcFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2lkcCc7XG5pbXBvcnQgeyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMnO1xuaW1wb3J0IHsgU0FNTEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvc2FtbCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBGZWRlcmF0ZWRBdXRoUHJvdmlkZXIgfSBmcm9tICcuL2ZlZGVyYXRlZCc7XG5cbmNvbnN0IFNBTUxfUFJPVklERVJfUFJFRklYID0gJ3NhbWwuJztcblxuLyoqXG4gKiBBbiB7QGxpbmsgQXV0aFByb3ZpZGVyfSBmb3IgU0FNTC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBTQU1MQXV0aFByb3ZpZGVyIGV4dGVuZHMgRmVkZXJhdGVkQXV0aFByb3ZpZGVyIHtcbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yLiBUaGUgcHJvdmlkZXJJZCBtdXN0IHN0YXJ0IHdpdGggXCJzYW1sLlwiXG4gICAqIEBwYXJhbSBwcm92aWRlcklkIC0gU0FNTCBwcm92aWRlciBJRC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByb3ZpZGVySWQ6IHN0cmluZykge1xuICAgIF9hc3NlcnQoXG4gICAgICBwcm92aWRlcklkLnN0YXJ0c1dpdGgoU0FNTF9QUk9WSURFUl9QUkVGSVgpLFxuICAgICAgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUlxuICAgICk7XG4gICAgc3VwZXIocHJvdmlkZXJJZCk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGFuIHtAbGluayBBdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBVc2VyQ3JlZGVudGlhbH0gYWZ0ZXIgYVxuICAgKiBzdWNjZXNzZnVsIFNBTUwgZmxvdyBjb21wbGV0ZXMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCB0byBnZXQgYW4ge0BsaW5rIEF1dGhDcmVkZW50aWFsfSwgeW91IGNvdWxkIHdyaXRlIHRoZVxuICAgKiBmb2xsb3dpbmcgY29kZTpcbiAgICpcbiAgICogYGBganNcbiAgICogY29uc3QgdXNlckNyZWRlbnRpYWwgPSBhd2FpdCBzaWduSW5XaXRoUG9wdXAoYXV0aCwgc2FtbFByb3ZpZGVyKTtcbiAgICogY29uc3QgY3JlZGVudGlhbCA9IFNBTUxBdXRoUHJvdmlkZXIuY3JlZGVudGlhbEZyb21SZXN1bHQodXNlckNyZWRlbnRpYWwpO1xuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsRnJvbVJlc3VsdChcbiAgICB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWxcbiAgKTogQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gU0FNTEF1dGhQcm92aWRlci5zYW1sQ3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3QoXG4gICAgICB1c2VyQ3JlZGVudGlhbCBhcyBVc2VyQ3JlZGVudGlhbEludGVybmFsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGV4dHJhY3QgdGhlIHVuZGVybHlpbmcge0BsaW5rIE9BdXRoQ3JlZGVudGlhbH0gZnJvbSBhIHtAbGluayBBdXRoRXJyb3J9IHdoaWNoIHdhc1xuICAgKiB0aHJvd24gZHVyaW5nIGEgc2lnbi1pbiwgbGluaywgb3IgcmVhdXRoZW50aWNhdGUgb3BlcmF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tRXJyb3IoZXJyb3I6IEZpcmViYXNlRXJyb3IpOiBBdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBTQU1MQXV0aFByb3ZpZGVyLnNhbWxDcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIChlcnJvci5jdXN0b21EYXRhIHx8IHt9KSBhcyBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiB7QGxpbmsgQXV0aENyZWRlbnRpYWx9IGZyb20gYSBKU09OIHN0cmluZyBvciBhIHBsYWluIG9iamVjdC5cbiAgICogQHBhcmFtIGpzb24gLSBBIHBsYWluIG9iamVjdCBvciBhIEpTT04gc3RyaW5nXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21KU09OKGpzb246IHN0cmluZyB8IG9iamVjdCk6IEF1dGhDcmVkZW50aWFsIHtcbiAgICBjb25zdCBjcmVkZW50aWFsID0gU0FNTEF1dGhDcmVkZW50aWFsLmZyb21KU09OKGpzb24pO1xuICAgIF9hc3NlcnQoY3JlZGVudGlhbCwgQXV0aEVycm9yQ29kZS5BUkdVTUVOVF9FUlJPUik7XG4gICAgcmV0dXJuIGNyZWRlbnRpYWw7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBzYW1sQ3JlZGVudGlhbEZyb21UYWdnZWRPYmplY3Qoe1xuICAgIF90b2tlblJlc3BvbnNlOiB0b2tlblJlc3BvbnNlXG4gIH06IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlKTogU0FNTEF1dGhDcmVkZW50aWFsIHwgbnVsbCB7XG4gICAgaWYgKCF0b2tlblJlc3BvbnNlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB7IHBlbmRpbmdUb2tlbiwgcHJvdmlkZXJJZCB9ID0gdG9rZW5SZXNwb25zZSBhcyBTaWduSW5XaXRoSWRwUmVzcG9uc2U7XG5cbiAgICBpZiAoIXBlbmRpbmdUb2tlbiB8fCAhcHJvdmlkZXJJZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBTQU1MQXV0aENyZWRlbnRpYWwuX2NyZWF0ZShwcm92aWRlcklkLCBwZW5kaW5nVG9rZW4pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIFR3aXR0ZXIgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5pbXBvcnQgeyBTaWduSW5XaXRoSWRwUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vaWRwJztcbmltcG9ydCB7IFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgT0F1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi4vY3JlZGVudGlhbHMvb2F1dGgnO1xuaW1wb3J0IHsgQmFzZU9BdXRoUHJvdmlkZXIgfSBmcm9tICcuL29hdXRoJztcbmltcG9ydCB7IFByb3ZpZGVySWQsIFNpZ25Jbk1ldGhvZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuLyoqXG4gKiBQcm92aWRlciBmb3IgZ2VuZXJhdGluZyBhbiB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmb3Ige0BsaW5rIFByb3ZpZGVySWR9LlRXSVRURVIuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIC8vIFNpZ24gaW4gdXNpbmcgYSByZWRpcmVjdC5cbiAqIGNvbnN0IHByb3ZpZGVyID0gbmV3IFR3aXR0ZXJBdXRoUHJvdmlkZXIoKTtcbiAqIC8vIFN0YXJ0IGEgc2lnbiBpbiBwcm9jZXNzIGZvciBhbiB1bmF1dGhlbnRpY2F0ZWQgdXNlci5cbiAqIGF3YWl0IHNpZ25JbldpdGhSZWRpcmVjdChhdXRoLCBwcm92aWRlcik7XG4gKiAvLyBUaGlzIHdpbGwgdHJpZ2dlciBhIGZ1bGwgcGFnZSByZWRpcmVjdCBhd2F5IGZyb20geW91ciBhcHBcbiAqXG4gKiAvLyBBZnRlciByZXR1cm5pbmcgZnJvbSB0aGUgcmVkaXJlY3Qgd2hlbiB5b3VyIGFwcCBpbml0aWFsaXplcyB5b3UgY2FuIG9idGFpbiB0aGUgcmVzdWx0XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRSZWRpcmVjdFJlc3VsdChhdXRoKTtcbiAqIGlmIChyZXN1bHQpIHtcbiAqICAgLy8gVGhpcyBpcyB0aGUgc2lnbmVkLWluIHVzZXJcbiAqICAgY29uc3QgdXNlciA9IHJlc3VsdC51c2VyO1xuICogICAvLyBUaGlzIGdpdmVzIHlvdSBhIFR3aXR0ZXIgQWNjZXNzIFRva2VuIGFuZCBTZWNyZXQuXG4gKiAgIGNvbnN0IGNyZWRlbnRpYWwgPSBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiAgIGNvbnN0IHRva2VuID0gY3JlZGVudGlhbC5hY2Nlc3NUb2tlbjtcbiAqICAgY29uc3Qgc2VjcmV0ID0gY3JlZGVudGlhbC5zZWNyZXQ7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogLy8gU2lnbiBpbiB1c2luZyBhIHBvcHVwLlxuICogY29uc3QgcHJvdmlkZXIgPSBuZXcgVHdpdHRlckF1dGhQcm92aWRlcigpO1xuICogY29uc3QgcmVzdWx0ID0gYXdhaXQgc2lnbkluV2l0aFBvcHVwKGF1dGgsIHByb3ZpZGVyKTtcbiAqXG4gKiAvLyBUaGUgc2lnbmVkLWluIHVzZXIgaW5mby5cbiAqIGNvbnN0IHVzZXIgPSByZXN1bHQudXNlcjtcbiAqIC8vIFRoaXMgZ2l2ZXMgeW91IGEgVHdpdHRlciBBY2Nlc3MgVG9rZW4gYW5kIFNlY3JldC5cbiAqIGNvbnN0IGNyZWRlbnRpYWwgPSBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tUmVzdWx0KHJlc3VsdCk7XG4gKiBjb25zdCB0b2tlbiA9IGNyZWRlbnRpYWwuYWNjZXNzVG9rZW47XG4gKiBjb25zdCBzZWNyZXQgPSBjcmVkZW50aWFsLnNlY3JldDtcbiAqIGBgYFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFR3aXR0ZXJBdXRoUHJvdmlkZXIgZXh0ZW5kcyBCYXNlT0F1dGhQcm92aWRlciB7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBTaWduSW5NZXRob2R9LlRXSVRURVIuICovXG4gIHN0YXRpYyByZWFkb25seSBUV0lUVEVSX1NJR05fSU5fTUVUSE9EOiAndHdpdHRlci5jb20nID0gU2lnbkluTWV0aG9kLlRXSVRURVI7XG4gIC8qKiBBbHdheXMgc2V0IHRvIHtAbGluayBQcm92aWRlcklkfS5UV0lUVEVSLiAqL1xuICBzdGF0aWMgcmVhZG9ubHkgUFJPVklERVJfSUQ6ICd0d2l0dGVyLmNvbScgPSBQcm92aWRlcklkLlRXSVRURVI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoUHJvdmlkZXJJZC5UV0lUVEVSKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY3JlZGVudGlhbCBmb3IgVHdpdHRlci5cbiAgICpcbiAgICogQHBhcmFtIHRva2VuIC0gVHdpdHRlciBhY2Nlc3MgdG9rZW4uXG4gICAqIEBwYXJhbSBzZWNyZXQgLSBUd2l0dGVyIHNlY3JldC5cbiAgICovXG4gIHN0YXRpYyBjcmVkZW50aWFsKHRva2VuOiBzdHJpbmcsIHNlY3JldDogc3RyaW5nKTogT0F1dGhDcmVkZW50aWFsIHtcbiAgICByZXR1cm4gT0F1dGhDcmVkZW50aWFsLl9mcm9tUGFyYW1zKHtcbiAgICAgIHByb3ZpZGVySWQ6IFR3aXR0ZXJBdXRoUHJvdmlkZXIuUFJPVklERVJfSUQsXG4gICAgICBzaWduSW5NZXRob2Q6IFR3aXR0ZXJBdXRoUHJvdmlkZXIuVFdJVFRFUl9TSUdOX0lOX01FVEhPRCxcbiAgICAgIG9hdXRoVG9rZW46IHRva2VuLFxuICAgICAgb2F1dGhUb2tlblNlY3JldDogc2VjcmV0XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCB0byBleHRyYWN0IHRoZSB1bmRlcmx5aW5nIHtAbGluayBPQXV0aENyZWRlbnRpYWx9IGZyb20gYSB7QGxpbmsgVXNlckNyZWRlbnRpYWx9LlxuICAgKlxuICAgKiBAcGFyYW0gdXNlckNyZWRlbnRpYWwgLSBUaGUgdXNlciBjcmVkZW50aWFsLlxuICAgKi9cbiAgc3RhdGljIGNyZWRlbnRpYWxGcm9tUmVzdWx0KFxuICAgIHVzZXJDcmVkZW50aWFsOiBVc2VyQ3JlZGVudGlhbFxuICApOiBPQXV0aENyZWRlbnRpYWwgfCBudWxsIHtcbiAgICByZXR1cm4gVHdpdHRlckF1dGhQcm92aWRlci5jcmVkZW50aWFsRnJvbVRhZ2dlZE9iamVjdChcbiAgICAgIHVzZXJDcmVkZW50aWFsIGFzIFVzZXJDcmVkZW50aWFsSW50ZXJuYWxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gZXh0cmFjdCB0aGUgdW5kZXJseWluZyB7QGxpbmsgT0F1dGhDcmVkZW50aWFsfSBmcm9tIGEge0BsaW5rIEF1dGhFcnJvcn0gd2hpY2ggd2FzXG4gICAqIHRocm93biBkdXJpbmcgYSBzaWduLWluLCBsaW5rLCBvciByZWF1dGhlbnRpY2F0ZSBvcGVyYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyQ3JlZGVudGlhbCAtIFRoZSB1c2VyIGNyZWRlbnRpYWwuXG4gICAqL1xuICBzdGF0aWMgY3JlZGVudGlhbEZyb21FcnJvcihlcnJvcjogRmlyZWJhc2VFcnJvcik6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIHJldHVybiBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KFxuICAgICAgKGVycm9yLmN1c3RvbURhdGEgfHwge30pIGFzIFRhZ2dlZFdpdGhUb2tlblJlc3BvbnNlXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWRlbnRpYWxGcm9tVGFnZ2VkT2JqZWN0KHtcbiAgICBfdG9rZW5SZXNwb25zZTogdG9rZW5SZXNwb25zZVxuICB9OiBUYWdnZWRXaXRoVG9rZW5SZXNwb25zZSk6IE9BdXRoQ3JlZGVudGlhbCB8IG51bGwge1xuICAgIGlmICghdG9rZW5SZXNwb25zZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHsgb2F1dGhBY2Nlc3NUb2tlbiwgb2F1dGhUb2tlblNlY3JldCB9ID1cbiAgICAgIHRva2VuUmVzcG9uc2UgYXMgU2lnbkluV2l0aElkcFJlc3BvbnNlO1xuICAgIGlmICghb2F1dGhBY2Nlc3NUb2tlbiB8fCAhb2F1dGhUb2tlblNlY3JldCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBUd2l0dGVyQXV0aFByb3ZpZGVyLmNyZWRlbnRpYWwob2F1dGhBY2Nlc3NUb2tlbiwgb2F1dGhUb2tlblNlY3JldCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBFbmRwb2ludCxcbiAgSHR0cE1ldGhvZCxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhVmVyc2lvbixcbiAgX2FkZFRpZElmTmVjZXNzYXJ5LFxuICBfcGVyZm9ybVNpZ25JblJlcXVlc3Rcbn0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnblVwUmVxdWVzdCB7XG4gIGlkVG9rZW4/OiBzdHJpbmc7XG4gIHJldHVyblNlY3VyZVRva2VuPzogYm9vbGVhbjtcbiAgZW1haWw/OiBzdHJpbmc7XG4gIHBhc3N3b3JkPzogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgY2FwdGNoYVJlc3BvbnNlPzogc3RyaW5nO1xuICBjbGllbnRUeXBlPzogUmVjYXB0Y2hhQ2xpZW50VHlwZTtcbiAgcmVjYXB0Y2hhVmVyc2lvbj86IFJlY2FwdGNoYVZlcnNpb247XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnblVwUmVzcG9uc2UgZXh0ZW5kcyBJZFRva2VuUmVzcG9uc2Uge1xuICBkaXNwbGF5TmFtZT86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduVXAoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25VcFJlcXVlc3Rcbik6IFByb21pc2U8U2lnblVwUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtU2lnbkluUmVxdWVzdDxTaWduVXBSZXF1ZXN0LCBTaWduVXBSZXNwb25zZT4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9VUCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBQaG9uZU9yT2F1dGhUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwsIFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IFVzZXJJbXBsIH0gZnJvbSAnLi91c2VyX2ltcGwnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlLCBQcm92aWRlcklkIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuXG5pbnRlcmZhY2UgVXNlckNyZWRlbnRpYWxQYXJhbXMge1xuICByZWFkb25seSB1c2VyOiBVc2VySW50ZXJuYWw7XG4gIHJlYWRvbmx5IHByb3ZpZGVySWQ6IFByb3ZpZGVySWQgfCBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBfdG9rZW5SZXNwb25zZT86IFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2U7XG4gIHJlYWRvbmx5IG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGU7XG59XG5cbmV4cG9ydCBjbGFzcyBVc2VyQ3JlZGVudGlhbEltcGxcbiAgaW1wbGVtZW50cyBVc2VyQ3JlZGVudGlhbEludGVybmFsLCBVc2VyQ3JlZGVudGlhbFBhcmFtc1xue1xuICByZWFkb25seSB1c2VyOiBVc2VySW50ZXJuYWw7XG4gIHJlYWRvbmx5IHByb3ZpZGVySWQ6IFByb3ZpZGVySWQgfCBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBfdG9rZW5SZXNwb25zZTogUGhvbmVPck9hdXRoVG9rZW5SZXNwb25zZSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgb3BlcmF0aW9uVHlwZTogT3BlcmF0aW9uVHlwZTtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXM6IFVzZXJDcmVkZW50aWFsUGFyYW1zKSB7XG4gICAgdGhpcy51c2VyID0gcGFyYW1zLnVzZXI7XG4gICAgdGhpcy5wcm92aWRlcklkID0gcGFyYW1zLnByb3ZpZGVySWQ7XG4gICAgdGhpcy5fdG9rZW5SZXNwb25zZSA9IHBhcmFtcy5fdG9rZW5SZXNwb25zZTtcbiAgICB0aGlzLm9wZXJhdGlvblR5cGUgPSBwYXJhbXMub3BlcmF0aW9uVHlwZTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBfZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgb3BlcmF0aW9uVHlwZTogT3BlcmF0aW9uVHlwZSxcbiAgICBpZFRva2VuUmVzcG9uc2U6IElkVG9rZW5SZXNwb25zZSxcbiAgICBpc0Fub255bW91czogYm9vbGVhbiA9IGZhbHNlXG4gICk6IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbnRlcm5hbD4ge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCBVc2VySW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICAgIGF1dGgsXG4gICAgICBpZFRva2VuUmVzcG9uc2UsXG4gICAgICBpc0Fub255bW91c1xuICAgICk7XG4gICAgY29uc3QgcHJvdmlkZXJJZCA9IHByb3ZpZGVySWRGb3JSZXNwb25zZShpZFRva2VuUmVzcG9uc2UpO1xuICAgIGNvbnN0IHVzZXJDcmVkID0gbmV3IFVzZXJDcmVkZW50aWFsSW1wbCh7XG4gICAgICB1c2VyLFxuICAgICAgcHJvdmlkZXJJZCxcbiAgICAgIF90b2tlblJlc3BvbnNlOiBpZFRva2VuUmVzcG9uc2UsXG4gICAgICBvcGVyYXRpb25UeXBlXG4gICAgfSk7XG4gICAgcmV0dXJuIHVzZXJDcmVkO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIF9mb3JPcGVyYXRpb24oXG4gICAgdXNlcjogVXNlckludGVybmFsLFxuICAgIG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGUsXG4gICAgcmVzcG9uc2U6IFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2VcbiAgKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbEltcGw+IHtcbiAgICBhd2FpdCB1c2VyLl91cGRhdGVUb2tlbnNJZk5lY2Vzc2FyeShyZXNwb25zZSwgLyogcmVsb2FkICovIHRydWUpO1xuICAgIGNvbnN0IHByb3ZpZGVySWQgPSBwcm92aWRlcklkRm9yUmVzcG9uc2UocmVzcG9uc2UpO1xuICAgIHJldHVybiBuZXcgVXNlckNyZWRlbnRpYWxJbXBsKHtcbiAgICAgIHVzZXIsXG4gICAgICBwcm92aWRlcklkLFxuICAgICAgX3Rva2VuUmVzcG9uc2U6IHJlc3BvbnNlLFxuICAgICAgb3BlcmF0aW9uVHlwZVxuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIHByb3ZpZGVySWRGb3JSZXNwb25zZShcbiAgcmVzcG9uc2U6IElkVG9rZW5SZXNwb25zZVxuKTogUHJvdmlkZXJJZCB8IHN0cmluZyB8IG51bGwge1xuICBpZiAocmVzcG9uc2UucHJvdmlkZXJJZCkge1xuICAgIHJldHVybiByZXNwb25zZS5wcm92aWRlcklkO1xuICB9XG5cbiAgaWYgKCdwaG9uZU51bWJlcicgaW4gcmVzcG9uc2UpIHtcbiAgICByZXR1cm4gUHJvdmlkZXJJZC5QSE9ORTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEF1dGgsIFVzZXJDcmVkZW50aWFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IHNpZ25VcCB9IGZyb20gJy4uLy4uL2FwaS9hdXRoZW50aWNhdGlvbi9zaWduX3VwJztcbmltcG9ydCB7IFVzZXJJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbXBsIH0gZnJvbSAnLi4vdXNlci91c2VyX2NyZWRlbnRpYWxfaW1wbCc7XG5pbXBvcnQgeyBfY2FzdEF1dGggfSBmcm9tICcuLi9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgX2lzRmlyZWJhc2VTZXJ2ZXJBcHAgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yIH0gZnJvbSAnLi4vLi4vY29yZS91dGlsL2Fzc2VydCc7XG5cbi8qKlxuICogQXN5bmNocm9ub3VzbHkgc2lnbnMgaW4gYXMgYW4gYW5vbnltb3VzIHVzZXIuXG4gKlxuICogQHJlbWFya3NcbiAqIElmIHRoZXJlIGlzIGFscmVhZHkgYW4gYW5vbnltb3VzIHVzZXIgc2lnbmVkIGluLCB0aGF0IHVzZXIgd2lsbCBiZSByZXR1cm5lZDsgb3RoZXJ3aXNlLCBhXG4gKiBuZXcgYW5vbnltb3VzIHVzZXIgaWRlbnRpdHkgd2lsbCBiZSBjcmVhdGVkIGFuZCByZXR1cm5lZC5cbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluQW5vbnltb3VzbHkoYXV0aDogQXV0aCk6IFByb21pc2U8VXNlckNyZWRlbnRpYWw+IHtcbiAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKGF1dGgpXG4gICAgKTtcbiAgfVxuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG4gIGF3YWl0IGF1dGhJbnRlcm5hbC5faW5pdGlhbGl6YXRpb25Qcm9taXNlO1xuICBpZiAoYXV0aEludGVybmFsLmN1cnJlbnRVc2VyPy5pc0Fub255bW91cykge1xuICAgIC8vIElmIGFuIGFub255bW91cyB1c2VyIGlzIGFscmVhZHkgc2lnbmVkIGluLCBubyBuZWVkIHRvIHNpZ24gdGhlbSBpbiBhZ2Fpbi5cbiAgICByZXR1cm4gbmV3IFVzZXJDcmVkZW50aWFsSW1wbCh7XG4gICAgICB1c2VyOiBhdXRoSW50ZXJuYWwuY3VycmVudFVzZXIgYXMgVXNlckludGVybmFsLFxuICAgICAgcHJvdmlkZXJJZDogbnVsbCxcbiAgICAgIG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGUuU0lHTl9JTlxuICAgIH0pO1xuICB9XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgc2lnblVwKGF1dGhJbnRlcm5hbCwge1xuICAgIHJldHVyblNlY3VyZVRva2VuOiB0cnVlXG4gIH0pO1xuICBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IFVzZXJDcmVkZW50aWFsSW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgT3BlcmF0aW9uVHlwZS5TSUdOX0lOLFxuICAgIHJlc3BvbnNlLFxuICAgIHRydWVcbiAgKTtcbiAgYXdhaXQgYXV0aEludGVybmFsLl91cGRhdGVDdXJyZW50VXNlcih1c2VyQ3JlZGVudGlhbC51c2VyKTtcbiAgcmV0dXJuIHVzZXJDcmVkZW50aWFsO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IE11bHRpRmFjdG9yRXJyb3IgYXMgTXVsdGlGYWN0b3JFcnJvclB1YmxpYyB9IGZyb20gJy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvYXV0aCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4uL2NvcmUvY3JlZGVudGlhbHMnO1xuaW1wb3J0IHsgSWRUb2tlbk1mYVJlc3BvbnNlIH0gZnJvbSAnLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vbW9kZWwvZW51bXMnO1xuXG5leHBvcnQgdHlwZSBNdWx0aUZhY3RvckVycm9yRGF0YSA9IE11bHRpRmFjdG9yRXJyb3JQdWJsaWNbJ2N1c3RvbURhdGEnXSAmIHtcbiAgX3NlcnZlclJlc3BvbnNlOiBJZFRva2VuTWZhUmVzcG9uc2U7XG59O1xuXG5leHBvcnQgY2xhc3MgTXVsdGlGYWN0b3JFcnJvclxuICBleHRlbmRzIEZpcmViYXNlRXJyb3JcbiAgaW1wbGVtZW50cyBNdWx0aUZhY3RvckVycm9yUHVibGljXG57XG4gIHJlYWRvbmx5IGN1c3RvbURhdGE6IE11bHRpRmFjdG9yRXJyb3JEYXRhO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGVycm9yOiBGaXJlYmFzZUVycm9yLFxuICAgIHJlYWRvbmx5IG9wZXJhdGlvblR5cGU6IE9wZXJhdGlvblR5cGUsXG4gICAgcmVhZG9ubHkgdXNlcj86IFVzZXJJbnRlcm5hbFxuICApIHtcbiAgICBzdXBlcihlcnJvci5jb2RlLCBlcnJvci5tZXNzYWdlKTtcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vTWljcm9zb2Z0L1R5cGVTY3JpcHQtd2lraS9ibG9iL21hc3Rlci9CcmVha2luZy1DaGFuZ2VzLm1kI2V4dGVuZGluZy1idWlsdC1pbnMtbGlrZS1lcnJvci1hcnJheS1hbmQtbWFwLW1heS1uby1sb25nZXItd29ya1xuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLCBNdWx0aUZhY3RvckVycm9yLnByb3RvdHlwZSk7XG4gICAgdGhpcy5jdXN0b21EYXRhID0ge1xuICAgICAgYXBwTmFtZTogYXV0aC5uYW1lLFxuICAgICAgdGVuYW50SWQ6IGF1dGgudGVuYW50SWQgPz8gdW5kZWZpbmVkLFxuICAgICAgX3NlcnZlclJlc3BvbnNlOiBlcnJvci5jdXN0b21EYXRhIS5fc2VydmVyUmVzcG9uc2UgYXMgSWRUb2tlbk1mYVJlc3BvbnNlLFxuICAgICAgb3BlcmF0aW9uVHlwZVxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgX2Zyb21FcnJvckFuZE9wZXJhdGlvbihcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgZXJyb3I6IEZpcmViYXNlRXJyb3IsXG4gICAgb3BlcmF0aW9uVHlwZTogT3BlcmF0aW9uVHlwZSxcbiAgICB1c2VyPzogVXNlckludGVybmFsXG4gICk6IE11bHRpRmFjdG9yRXJyb3Ige1xuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JFcnJvcihhdXRoLCBlcnJvciwgb3BlcmF0aW9uVHlwZSwgdXNlcik7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9wcm9jZXNzQ3JlZGVudGlhbFNhdmluZ01mYUNvbnRleHRJZk5lY2Vzc2FyeShcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICBvcGVyYXRpb25UeXBlOiBPcGVyYXRpb25UeXBlLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgdXNlcj86IFVzZXJJbnRlcm5hbFxuKTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+IHtcbiAgY29uc3QgaWRUb2tlblByb3ZpZGVyID1cbiAgICBvcGVyYXRpb25UeXBlID09PSBPcGVyYXRpb25UeXBlLlJFQVVUSEVOVElDQVRFXG4gICAgICA/IGNyZWRlbnRpYWwuX2dldFJlYXV0aGVudGljYXRpb25SZXNvbHZlcihhdXRoKVxuICAgICAgOiBjcmVkZW50aWFsLl9nZXRJZFRva2VuUmVzcG9uc2UoYXV0aCk7XG5cbiAgcmV0dXJuIGlkVG9rZW5Qcm92aWRlci5jYXRjaChlcnJvciA9PiB7XG4gICAgaWYgKGVycm9yLmNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5NRkFfUkVRVUlSRUR9YCkge1xuICAgICAgdGhyb3cgTXVsdGlGYWN0b3JFcnJvci5fZnJvbUVycm9yQW5kT3BlcmF0aW9uKFxuICAgICAgICBhdXRoLFxuICAgICAgICBlcnJvcixcbiAgICAgICAgb3BlcmF0aW9uVHlwZSxcbiAgICAgICAgdXNlclxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aHJvdyBlcnJvcjtcbiAgfSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlckFzc29jaWF0ZWRPYmplY3Qge1xuICBwcm92aWRlcklkPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRha2VzIGEgc2V0IG9mIFVzZXJJbmZvIHByb3ZpZGVyIGRhdGEgYW5kIGNvbnZlcnRzIGl0IHRvIGEgc2V0IG9mIG5hbWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlckRhdGFBc05hbWVzPFQgZXh0ZW5kcyBQcm92aWRlckFzc29jaWF0ZWRPYmplY3Q+KFxuICBwcm92aWRlckRhdGE6IFRbXVxuKTogU2V0PHN0cmluZz4ge1xuICByZXR1cm4gbmV3IFNldChcbiAgICBwcm92aWRlckRhdGFcbiAgICAgIC5tYXAoKHsgcHJvdmlkZXJJZCB9KSA9PiBwcm92aWRlcklkKVxuICAgICAgLmZpbHRlcihwaWQgPT4gISFwaWQpIGFzIHN0cmluZ1tdXG4gICk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IGRlbGV0ZUxpbmtlZEFjY291bnRzIH0gZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9hY2NvdW50JztcbmltcG9ydCB7IFVzZXJJbnRlcm5hbCwgVXNlckNyZWRlbnRpYWxJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuLi9jcmVkZW50aWFscyc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBwcm92aWRlckRhdGFBc05hbWVzIH0gZnJvbSAnLi4vdXRpbC9wcm92aWRlcnMnO1xuaW1wb3J0IHsgX2xvZ291dElmSW52YWxpZGF0ZWQgfSBmcm9tICcuL2ludmFsaWRhdGlvbic7XG5pbXBvcnQgeyBfcmVsb2FkV2l0aG91dFNhdmluZyB9IGZyb20gJy4vcmVsb2FkJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW1wbCB9IGZyb20gJy4vdXNlcl9jcmVkZW50aWFsX2ltcGwnO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgT3BlcmF0aW9uVHlwZSwgUHJvdmlkZXJJZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcblxuLyoqXG4gKiBVbmxpbmtzIGEgcHJvdmlkZXIgZnJvbSBhIHVzZXIgYWNjb3VudC5cbiAqXG4gKiBAcGFyYW0gdXNlciAtIFRoZSB1c2VyLlxuICogQHBhcmFtIHByb3ZpZGVySWQgLSBUaGUgcHJvdmlkZXIgdG8gdW5saW5rLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVubGluayh1c2VyOiBVc2VyLCBwcm92aWRlcklkOiBzdHJpbmcpOiBQcm9taXNlPFVzZXI+IHtcbiAgY29uc3QgdXNlckludGVybmFsID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbDtcbiAgYXdhaXQgX2Fzc2VydExpbmtlZFN0YXR1cyh0cnVlLCB1c2VySW50ZXJuYWwsIHByb3ZpZGVySWQpO1xuICBjb25zdCB7IHByb3ZpZGVyVXNlckluZm8gfSA9IGF3YWl0IGRlbGV0ZUxpbmtlZEFjY291bnRzKHVzZXJJbnRlcm5hbC5hdXRoLCB7XG4gICAgaWRUb2tlbjogYXdhaXQgdXNlckludGVybmFsLmdldElkVG9rZW4oKSxcbiAgICBkZWxldGVQcm92aWRlcjogW3Byb3ZpZGVySWRdXG4gIH0pO1xuXG4gIGNvbnN0IHByb3ZpZGVyc0xlZnQgPSBwcm92aWRlckRhdGFBc05hbWVzKHByb3ZpZGVyVXNlckluZm8gfHwgW10pO1xuXG4gIHVzZXJJbnRlcm5hbC5wcm92aWRlckRhdGEgPSB1c2VySW50ZXJuYWwucHJvdmlkZXJEYXRhLmZpbHRlcihwZCA9PlxuICAgIHByb3ZpZGVyc0xlZnQuaGFzKHBkLnByb3ZpZGVySWQpXG4gICk7XG4gIGlmICghcHJvdmlkZXJzTGVmdC5oYXMoUHJvdmlkZXJJZC5QSE9ORSkpIHtcbiAgICB1c2VySW50ZXJuYWwucGhvbmVOdW1iZXIgPSBudWxsO1xuICB9XG5cbiAgYXdhaXQgdXNlckludGVybmFsLmF1dGguX3BlcnNpc3RVc2VySWZDdXJyZW50KHVzZXJJbnRlcm5hbCk7XG4gIHJldHVybiB1c2VySW50ZXJuYWw7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBfbGluayhcbiAgdXNlcjogVXNlckludGVybmFsLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgYnlwYXNzQXV0aFN0YXRlID0gZmFsc2Vcbik6IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbnRlcm5hbD4ge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgIHVzZXIsXG4gICAgY3JlZGVudGlhbC5fbGlua1RvSWRUb2tlbih1c2VyLmF1dGgsIGF3YWl0IHVzZXIuZ2V0SWRUb2tlbigpKSxcbiAgICBieXBhc3NBdXRoU3RhdGVcbiAgKTtcbiAgcmV0dXJuIFVzZXJDcmVkZW50aWFsSW1wbC5fZm9yT3BlcmF0aW9uKHVzZXIsIE9wZXJhdGlvblR5cGUuTElOSywgcmVzcG9uc2UpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gX2Fzc2VydExpbmtlZFN0YXR1cyhcbiAgZXhwZWN0ZWQ6IGJvb2xlYW4sXG4gIHVzZXI6IFVzZXJJbnRlcm5hbCxcbiAgcHJvdmlkZXI6IHN0cmluZ1xuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IF9yZWxvYWRXaXRob3V0U2F2aW5nKHVzZXIpO1xuICBjb25zdCBwcm92aWRlcklkcyA9IHByb3ZpZGVyRGF0YUFzTmFtZXModXNlci5wcm92aWRlckRhdGEpO1xuXG4gIGNvbnN0IGNvZGUgPVxuICAgIGV4cGVjdGVkID09PSBmYWxzZVxuICAgICAgPyBBdXRoRXJyb3JDb2RlLlBST1ZJREVSX0FMUkVBRFlfTElOS0VEXG4gICAgICA6IEF1dGhFcnJvckNvZGUuTk9fU1VDSF9QUk9WSURFUjtcbiAgX2Fzc2VydChwcm92aWRlcklkcy5oYXMocHJvdmlkZXIpID09PSBleHBlY3RlZCwgdXNlci5hdXRoLCBjb2RlKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBGaXJlYmFzZUVycm9yIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgX3Byb2Nlc3NDcmVkZW50aWFsU2F2aW5nTWZhQ29udGV4dElmTmVjZXNzYXJ5IH0gZnJvbSAnLi4vLi4vbWZhL21mYV9lcnJvcic7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBBdXRoQ3JlZGVudGlhbCB9IGZyb20gJy4uL2NyZWRlbnRpYWxzJztcbmltcG9ydCB7IEF1dGhFcnJvckNvZGUgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCwgX2ZhaWwgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfcGFyc2VUb2tlbiB9IGZyb20gJy4vaWRfdG9rZW5fcmVzdWx0JztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbXBsIH0gZnJvbSAnLi91c2VyX2NyZWRlbnRpYWxfaW1wbCc7XG5pbXBvcnQgeyBfaXNGaXJlYmFzZVNlcnZlckFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvYXNzZXJ0JztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9yZWF1dGhlbnRpY2F0ZShcbiAgdXNlcjogVXNlckludGVybmFsLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgYnlwYXNzQXV0aFN0YXRlID0gZmFsc2Vcbik6IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbXBsPiB7XG4gIGNvbnN0IHsgYXV0aCB9ID0gdXNlcjtcbiAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKGF1dGgpXG4gICAgKTtcbiAgfVxuICBjb25zdCBvcGVyYXRpb25UeXBlID0gT3BlcmF0aW9uVHlwZS5SRUFVVEhFTlRJQ0FURTtcblxuICB0cnkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQoXG4gICAgICB1c2VyLFxuICAgICAgX3Byb2Nlc3NDcmVkZW50aWFsU2F2aW5nTWZhQ29udGV4dElmTmVjZXNzYXJ5KFxuICAgICAgICBhdXRoLFxuICAgICAgICBvcGVyYXRpb25UeXBlLFxuICAgICAgICBjcmVkZW50aWFsLFxuICAgICAgICB1c2VyXG4gICAgICApLFxuICAgICAgYnlwYXNzQXV0aFN0YXRlXG4gICAgKTtcbiAgICBfYXNzZXJ0KHJlc3BvbnNlLmlkVG9rZW4sIGF1dGgsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIGNvbnN0IHBhcnNlZCA9IF9wYXJzZVRva2VuKHJlc3BvbnNlLmlkVG9rZW4pO1xuICAgIF9hc3NlcnQocGFyc2VkLCBhdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcblxuICAgIGNvbnN0IHsgc3ViOiBsb2NhbElkIH0gPSBwYXJzZWQ7XG4gICAgX2Fzc2VydCh1c2VyLnVpZCA9PT0gbG9jYWxJZCwgYXV0aCwgQXV0aEVycm9yQ29kZS5VU0VSX01JU01BVENIKTtcblxuICAgIHJldHVybiBVc2VyQ3JlZGVudGlhbEltcGwuX2Zvck9wZXJhdGlvbih1c2VyLCBvcGVyYXRpb25UeXBlLCByZXNwb25zZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBDb252ZXJ0IHVzZXIgZGVsZXRlZCBlcnJvciBpbnRvIHVzZXIgbWlzbWF0Y2hcbiAgICBpZiAoKGUgYXMgRmlyZWJhc2VFcnJvcik/LmNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5VU0VSX0RFTEVURUR9YCkge1xuICAgICAgX2ZhaWwoYXV0aCwgQXV0aEVycm9yQ29kZS5VU0VSX01JU01BVENIKTtcbiAgICB9XG4gICAgdGhyb3cgZTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsLCBBdXRoLCBVc2VyIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgX3Byb2Nlc3NDcmVkZW50aWFsU2F2aW5nTWZhQ29udGV4dElmTmVjZXNzYXJ5IH0gZnJvbSAnLi4vLi4vbWZhL21mYV9lcnJvcic7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7IFVzZXJJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL3VzZXInO1xuaW1wb3J0IHsgQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuLi9jcmVkZW50aWFscyc7XG5pbXBvcnQgeyBfYXNzZXJ0TGlua2VkU3RhdHVzLCBfbGluayB9IGZyb20gJy4uL3VzZXIvbGlua191bmxpbmsnO1xuaW1wb3J0IHsgX3JlYXV0aGVudGljYXRlIH0gZnJvbSAnLi4vdXNlci9yZWF1dGhlbnRpY2F0ZSc7XG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbEltcGwgfSBmcm9tICcuLi91c2VyL3VzZXJfY3JlZGVudGlhbF9pbXBsJztcbmltcG9ydCB7IF9jYXN0QXV0aCB9IGZyb20gJy4uL2F1dGgvYXV0aF9pbXBsJztcbmltcG9ydCB7IGdldE1vZHVsYXJJbnN0YW5jZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IE9wZXJhdGlvblR5cGUgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5pbXBvcnQgeyBfaXNGaXJlYmFzZVNlcnZlckFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvYXNzZXJ0JztcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIF9zaWduSW5XaXRoQ3JlZGVudGlhbChcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbCxcbiAgYnlwYXNzQXV0aFN0YXRlID0gZmFsc2Vcbik6IFByb21pc2U8VXNlckNyZWRlbnRpYWw+IHtcbiAgaWYgKF9pc0ZpcmViYXNlU2VydmVyQXBwKGF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKGF1dGgpXG4gICAgKTtcbiAgfVxuICBjb25zdCBvcGVyYXRpb25UeXBlID0gT3BlcmF0aW9uVHlwZS5TSUdOX0lOO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9wcm9jZXNzQ3JlZGVudGlhbFNhdmluZ01mYUNvbnRleHRJZk5lY2Vzc2FyeShcbiAgICBhdXRoLFxuICAgIG9wZXJhdGlvblR5cGUsXG4gICAgY3JlZGVudGlhbFxuICApO1xuICBjb25zdCB1c2VyQ3JlZGVudGlhbCA9IGF3YWl0IFVzZXJDcmVkZW50aWFsSW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoLFxuICAgIG9wZXJhdGlvblR5cGUsXG4gICAgcmVzcG9uc2VcbiAgKTtcblxuICBpZiAoIWJ5cGFzc0F1dGhTdGF0ZSkge1xuICAgIGF3YWl0IGF1dGguX3VwZGF0ZUN1cnJlbnRVc2VyKHVzZXJDcmVkZW50aWFsLnVzZXIpO1xuICB9XG4gIHJldHVybiB1c2VyQ3JlZGVudGlhbDtcbn1cblxuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzaWducyBpbiB3aXRoIHRoZSBnaXZlbiBjcmVkZW50aWFscy5cbiAqXG4gKiBAcmVtYXJrc1xuICogQW4ge0BsaW5rIEF1dGhQcm92aWRlcn0gY2FuIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGNyZWRlbnRpYWwuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGNyZWRlbnRpYWwgLSBUaGUgYXV0aCBjcmVkZW50aWFsLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbldpdGhDcmVkZW50aWFsKFxuICBhdXRoOiBBdXRoLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbFxuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICByZXR1cm4gX3NpZ25JbldpdGhDcmVkZW50aWFsKF9jYXN0QXV0aChhdXRoKSwgY3JlZGVudGlhbCk7XG59XG5cbi8qKlxuICogTGlua3MgdGhlIHVzZXIgYWNjb3VudCB3aXRoIHRoZSBnaXZlbiBjcmVkZW50aWFscy5cbiAqXG4gKiBAcmVtYXJrc1xuICogQW4ge0BsaW5rIEF1dGhQcm92aWRlcn0gY2FuIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGNyZWRlbnRpYWwuXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBjcmVkZW50aWFsIC0gVGhlIGF1dGggY3JlZGVudGlhbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaW5rV2l0aENyZWRlbnRpYWwoXG4gIHVzZXI6IFVzZXIsXG4gIGNyZWRlbnRpYWw6IEF1dGhDcmVkZW50aWFsXG4pOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbCA9IGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWw7XG5cbiAgYXdhaXQgX2Fzc2VydExpbmtlZFN0YXR1cyhmYWxzZSwgdXNlckludGVybmFsLCBjcmVkZW50aWFsLnByb3ZpZGVySWQpO1xuXG4gIHJldHVybiBfbGluayh1c2VySW50ZXJuYWwsIGNyZWRlbnRpYWwpO1xufVxuXG4vKipcbiAqIFJlLWF1dGhlbnRpY2F0ZXMgYSB1c2VyIHVzaW5nIGEgZnJlc2ggY3JlZGVudGlhbC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVXNlIGJlZm9yZSBvcGVyYXRpb25zIHN1Y2ggYXMge0BsaW5rIHVwZGF0ZVBhc3N3b3JkfSB0aGF0IHJlcXVpcmUgdG9rZW5zIGZyb20gcmVjZW50IHNpZ24taW5cbiAqIGF0dGVtcHRzLiBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCB0byByZWNvdmVyIGZyb20gYSBgQ1JFREVOVElBTF9UT09fT0xEX0xPR0lOX0FHQUlOYCBlcnJvclxuICogb3IgYSBgVE9LRU5fRVhQSVJFRGAgZXJyb3IuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBvbiBhbnkge0BsaW5rIFVzZXJ9IHNpZ25lZCBpbiBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzXG4gKiBjcmVhdGVkIHdpdGggYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBjcmVkZW50aWFsIC0gVGhlIGF1dGggY3JlZGVudGlhbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWF1dGhlbnRpY2F0ZVdpdGhDcmVkZW50aWFsKFxuICB1c2VyOiBVc2VyLFxuICBjcmVkZW50aWFsOiBBdXRoQ3JlZGVudGlhbFxuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICByZXR1cm4gX3JlYXV0aGVudGljYXRlKGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWwsIGNyZWRlbnRpYWwpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEVuZHBvaW50LFxuICBIdHRwTWV0aG9kLFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIF9wZXJmb3JtU2lnbkluUmVxdWVzdFxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTaWduSW5XaXRoQ3VzdG9tVG9rZW5SZXF1ZXN0IHtcbiAgdG9rZW46IHN0cmluZztcbiAgcmV0dXJuU2VjdXJlVG9rZW46IGJvb2xlYW47XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNpZ25JbldpdGhDdXN0b21Ub2tlblJlc3BvbnNlIGV4dGVuZHMgSWRUb2tlblJlc3BvbnNlIHt9XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduSW5XaXRoQ3VzdG9tVG9rZW4oXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFNpZ25JbldpdGhDdXN0b21Ub2tlblJlcXVlc3Rcbik6IFByb21pc2U8U2lnbkluV2l0aEN1c3RvbVRva2VuUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtU2lnbkluUmVxdWVzdDxcbiAgICBTaWduSW5XaXRoQ3VzdG9tVG9rZW5SZXF1ZXN0LFxuICAgIFNpZ25JbldpdGhDdXN0b21Ub2tlblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU0lHTl9JTl9XSVRIX0NVU1RPTV9UT0tFTixcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBBdXRoLCBVc2VyQ3JlZGVudGlhbCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IHNpZ25JbldpdGhDdXN0b21Ub2tlbiBhcyBnZXRJZFRva2VuUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vY3VzdG9tX3Rva2VuJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW1wbCB9IGZyb20gJy4uL3VzZXIvdXNlcl9jcmVkZW50aWFsX2ltcGwnO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vYXV0aC9hdXRoX2ltcGwnO1xuaW1wb3J0IHsgT3BlcmF0aW9uVHlwZSB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvciB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzaWducyBpbiB1c2luZyBhIGN1c3RvbSB0b2tlbi5cbiAqXG4gKiBAcmVtYXJrc1xuICogQ3VzdG9tIHRva2VucyBhcmUgdXNlZCB0byBpbnRlZ3JhdGUgRmlyZWJhc2UgQXV0aCB3aXRoIGV4aXN0aW5nIGF1dGggc3lzdGVtcywgYW5kIG11c3RcbiAqIGJlIGdlbmVyYXRlZCBieSBhbiBhdXRoIGJhY2tlbmQgdXNpbmcgdGhlXG4gKiB7QGxpbmsgaHR0cHM6Ly9maXJlYmFzZS5nb29nbGUuY29tL2RvY3MvcmVmZXJlbmNlL2FkbWluL25vZGUvYWRtaW4uYXV0aC5BdXRoI2NyZWF0ZWN1c3RvbXRva2VuIHwgY3JlYXRlQ3VzdG9tVG9rZW59XG4gKiBtZXRob2QgaW4gdGhlIHtAbGluayBodHRwczovL2ZpcmViYXNlLmdvb2dsZS5jb20vZG9jcy9hdXRoL2FkbWluIHwgQWRtaW4gU0RLfSAuXG4gKlxuICogRmFpbHMgd2l0aCBhbiBlcnJvciBpZiB0aGUgdG9rZW4gaXMgaW52YWxpZCwgZXhwaXJlZCwgb3Igbm90IGFjY2VwdGVkIGJ5IHRoZSBGaXJlYmFzZSBBdXRoIHNlcnZpY2UuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGN1c3RvbVRva2VuIC0gVGhlIGN1c3RvbSB0b2tlbiB0byBzaWduIGluIHdpdGguXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aEN1c3RvbVRva2VuKFxuICBhdXRoOiBBdXRoLFxuICBjdXN0b21Ub2tlbjogc3RyaW5nXG4pOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcChhdXRoLmFwcCkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcihhdXRoKVxuICAgICk7XG4gIH1cbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICBjb25zdCByZXNwb25zZTogSWRUb2tlblJlc3BvbnNlID0gYXdhaXQgZ2V0SWRUb2tlblJlc3BvbnNlKGF1dGhJbnRlcm5hbCwge1xuICAgIHRva2VuOiBjdXN0b21Ub2tlbixcbiAgICByZXR1cm5TZWN1cmVUb2tlbjogdHJ1ZVxuICB9KTtcbiAgY29uc3QgY3JlZCA9IGF3YWl0IFVzZXJDcmVkZW50aWFsSW1wbC5fZnJvbUlkVG9rZW5SZXNwb25zZShcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgT3BlcmF0aW9uVHlwZS5TSUdOX0lOLFxuICAgIHJlc3BvbnNlXG4gICk7XG4gIGF3YWl0IGF1dGhJbnRlcm5hbC5fdXBkYXRlQ3VycmVudFVzZXIoY3JlZC51c2VyKTtcbiAgcmV0dXJuIGNyZWQ7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRmFjdG9ySWQsXG4gIE11bHRpRmFjdG9ySW5mbyxcbiAgUGhvbmVNdWx0aUZhY3RvckluZm8sXG4gIFRvdHBNdWx0aUZhY3RvckluZm9cbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7XG4gIFBob25lTWZhRW5yb2xsbWVudCxcbiAgTWZhRW5yb2xsbWVudCxcbiAgVG90cE1mYUVucm9sbG1lbnRcbn0gZnJvbSAnLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9tZmEnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2NvcmUvZXJyb3JzJztcbmltcG9ydCB7IF9mYWlsIH0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi9tb2RlbC9hdXRoJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE11bHRpRmFjdG9ySW5mb0ltcGwgaW1wbGVtZW50cyBNdWx0aUZhY3RvckluZm8ge1xuICByZWFkb25seSB1aWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZGlzcGxheU5hbWU/OiBzdHJpbmcgfCBudWxsO1xuICByZWFkb25seSBlbnJvbGxtZW50VGltZTogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihyZWFkb25seSBmYWN0b3JJZDogRmFjdG9ySWQsIHJlc3BvbnNlOiBNZmFFbnJvbGxtZW50KSB7XG4gICAgdGhpcy51aWQgPSByZXNwb25zZS5tZmFFbnJvbGxtZW50SWQ7XG4gICAgdGhpcy5lbnJvbGxtZW50VGltZSA9IG5ldyBEYXRlKHJlc3BvbnNlLmVucm9sbGVkQXQpLnRvVVRDU3RyaW5nKCk7XG4gICAgdGhpcy5kaXNwbGF5TmFtZSA9IHJlc3BvbnNlLmRpc3BsYXlOYW1lO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIGVucm9sbG1lbnQ6IE1mYUVucm9sbG1lbnRcbiAgKTogTXVsdGlGYWN0b3JJbmZvSW1wbCB7XG4gICAgaWYgKCdwaG9uZUluZm8nIGluIGVucm9sbG1lbnQpIHtcbiAgICAgIHJldHVybiBQaG9uZU11bHRpRmFjdG9ySW5mb0ltcGwuX2Zyb21TZXJ2ZXJSZXNwb25zZShhdXRoLCBlbnJvbGxtZW50KTtcbiAgICB9IGVsc2UgaWYgKCd0b3RwSW5mbycgaW4gZW5yb2xsbWVudCkge1xuICAgICAgcmV0dXJuIFRvdHBNdWx0aUZhY3RvckluZm9JbXBsLl9mcm9tU2VydmVyUmVzcG9uc2UoYXV0aCwgZW5yb2xsbWVudCk7XG4gICAgfVxuICAgIHJldHVybiBfZmFpbChhdXRoLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUGhvbmVNdWx0aUZhY3RvckluZm9JbXBsXG4gIGV4dGVuZHMgTXVsdGlGYWN0b3JJbmZvSW1wbFxuICBpbXBsZW1lbnRzIFBob25lTXVsdGlGYWN0b3JJbmZvXG57XG4gIHJlYWRvbmx5IHBob25lTnVtYmVyOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihyZXNwb25zZTogUGhvbmVNZmFFbnJvbGxtZW50KSB7XG4gICAgc3VwZXIoRmFjdG9ySWQuUEhPTkUsIHJlc3BvbnNlKTtcbiAgICB0aGlzLnBob25lTnVtYmVyID0gcmVzcG9uc2UucGhvbmVJbmZvO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgX2F1dGg6IEF1dGhJbnRlcm5hbCxcbiAgICBlbnJvbGxtZW50OiBNZmFFbnJvbGxtZW50XG4gICk6IFBob25lTXVsdGlGYWN0b3JJbmZvSW1wbCB7XG4gICAgcmV0dXJuIG5ldyBQaG9uZU11bHRpRmFjdG9ySW5mb0ltcGwoZW5yb2xsbWVudCBhcyBQaG9uZU1mYUVucm9sbG1lbnQpO1xuICB9XG59XG5leHBvcnQgY2xhc3MgVG90cE11bHRpRmFjdG9ySW5mb0ltcGxcbiAgZXh0ZW5kcyBNdWx0aUZhY3RvckluZm9JbXBsXG4gIGltcGxlbWVudHMgVG90cE11bHRpRmFjdG9ySW5mb1xue1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHJlc3BvbnNlOiBUb3RwTWZhRW5yb2xsbWVudCkge1xuICAgIHN1cGVyKEZhY3RvcklkLlRPVFAsIHJlc3BvbnNlKTtcbiAgfVxuXG4gIHN0YXRpYyBfZnJvbVNlcnZlclJlc3BvbnNlKFxuICAgIF9hdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgZW5yb2xsbWVudDogTWZhRW5yb2xsbWVudFxuICApOiBUb3RwTXVsdGlGYWN0b3JJbmZvSW1wbCB7XG4gICAgcmV0dXJuIG5ldyBUb3RwTXVsdGlGYWN0b3JJbmZvSW1wbChlbnJvbGxtZW50IGFzIFRvdHBNZmFFbnJvbGxtZW50KTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IEFjdGlvbkNvZGVTZXR0aW5ncywgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCB7IEdldE9vYkNvZGVSZXF1ZXN0IH0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0KFxuICBhdXRoOiBBdXRoLFxuICByZXF1ZXN0OiBHZXRPb2JDb2RlUmVxdWVzdCxcbiAgYWN0aW9uQ29kZVNldHRpbmdzOiBBY3Rpb25Db2RlU2V0dGluZ3Ncbik6IHZvaWQge1xuICBfYXNzZXJ0KFxuICAgIGFjdGlvbkNvZGVTZXR0aW5ncy51cmw/Lmxlbmd0aCA+IDAsXG4gICAgYXV0aCxcbiAgICBBdXRoRXJyb3JDb2RlLklOVkFMSURfQ09OVElOVUVfVVJJXG4gICk7XG4gIF9hc3NlcnQoXG4gICAgdHlwZW9mIGFjdGlvbkNvZGVTZXR0aW5ncy5keW5hbWljTGlua0RvbWFpbiA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgIGFjdGlvbkNvZGVTZXR0aW5ncy5keW5hbWljTGlua0RvbWFpbi5sZW5ndGggPiAwLFxuICAgIGF1dGgsXG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX0RZTkFNSUNfTElOS19ET01BSU5cbiAgKTtcbiAgX2Fzc2VydChcbiAgICB0eXBlb2YgYWN0aW9uQ29kZVNldHRpbmdzLmxpbmtEb21haW4gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgICBhY3Rpb25Db2RlU2V0dGluZ3MubGlua0RvbWFpbi5sZW5ndGggPiAwLFxuICAgIGF1dGgsXG4gICAgQXV0aEVycm9yQ29kZS5JTlZBTElEX0hPU1RJTkdfTElOS19ET01BSU5cbiAgKTtcblxuICByZXF1ZXN0LmNvbnRpbnVlVXJsID0gYWN0aW9uQ29kZVNldHRpbmdzLnVybDtcbiAgcmVxdWVzdC5keW5hbWljTGlua0RvbWFpbiA9IGFjdGlvbkNvZGVTZXR0aW5ncy5keW5hbWljTGlua0RvbWFpbjtcbiAgcmVxdWVzdC5saW5rRG9tYWluID0gYWN0aW9uQ29kZVNldHRpbmdzLmxpbmtEb21haW47XG4gIHJlcXVlc3QuY2FuSGFuZGxlQ29kZUluQXBwID0gYWN0aW9uQ29kZVNldHRpbmdzLmhhbmRsZUNvZGVJbkFwcDtcblxuICBpZiAoYWN0aW9uQ29kZVNldHRpbmdzLmlPUykge1xuICAgIF9hc3NlcnQoXG4gICAgICBhY3Rpb25Db2RlU2V0dGluZ3MuaU9TLmJ1bmRsZUlkLmxlbmd0aCA+IDAsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX0lPU19CVU5ETEVfSURcbiAgICApO1xuICAgIHJlcXVlc3QuaU9TQnVuZGxlSWQgPSBhY3Rpb25Db2RlU2V0dGluZ3MuaU9TLmJ1bmRsZUlkO1xuICB9XG5cbiAgaWYgKGFjdGlvbkNvZGVTZXR0aW5ncy5hbmRyb2lkKSB7XG4gICAgX2Fzc2VydChcbiAgICAgIGFjdGlvbkNvZGVTZXR0aW5ncy5hbmRyb2lkLnBhY2thZ2VOYW1lLmxlbmd0aCA+IDAsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5NSVNTSU5HX0FORFJPSURfUEFDS0FHRV9OQU1FXG4gICAgKTtcbiAgICByZXF1ZXN0LmFuZHJvaWRJbnN0YWxsQXBwID0gYWN0aW9uQ29kZVNldHRpbmdzLmFuZHJvaWQuaW5zdGFsbEFwcDtcbiAgICByZXF1ZXN0LmFuZHJvaWRNaW5pbXVtVmVyc2lvbkNvZGUgPVxuICAgICAgYWN0aW9uQ29kZVNldHRpbmdzLmFuZHJvaWQubWluaW11bVZlcnNpb247XG4gICAgcmVxdWVzdC5hbmRyb2lkUGFja2FnZU5hbWUgPSBhY3Rpb25Db2RlU2V0dGluZ3MuYW5kcm9pZC5wYWNrYWdlTmFtZTtcbiAgfVxufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEFjdGlvbkNvZGVJbmZvLFxuICBBY3Rpb25Db2RlT3BlcmF0aW9uLFxuICBBY3Rpb25Db2RlU2V0dGluZ3MsXG4gIEF1dGgsXG4gIFVzZXJDcmVkZW50aWFsXG59IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmltcG9ydCAqIGFzIGFjY291bnQgZnJvbSAnLi4vLi4vYXBpL2FjY291bnRfbWFuYWdlbWVudC9lbWFpbF9hbmRfcGFzc3dvcmQnO1xuaW1wb3J0ICogYXMgYXV0aGVudGljYXRpb24gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBzaWduVXAsIFNpZ25VcFJlcXVlc3QgfSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vc2lnbl91cCc7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckluZm9JbXBsIH0gZnJvbSAnLi4vLi4vbWZhL21mYV9pbmZvJztcbmltcG9ydCB7IEVtYWlsQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi4vcHJvdmlkZXJzL2VtYWlsJztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW1wbCB9IGZyb20gJy4uL3VzZXIvdXNlcl9jcmVkZW50aWFsX2ltcGwnO1xuaW1wb3J0IHtcbiAgX2Fzc2VydCxcbiAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3Jcbn0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdCB9IGZyb20gJy4vYWN0aW9uX2NvZGVfc2V0dGluZ3MnO1xuaW1wb3J0IHsgc2lnbkluV2l0aENyZWRlbnRpYWwgfSBmcm9tICcuL2NyZWRlbnRpYWwnO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vYXV0aC9hdXRoX2ltcGwnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vLi4vbW9kZWwvZW51bXMnO1xuaW1wb3J0IHsgaGFuZGxlUmVjYXB0Y2hhRmxvdyB9IGZyb20gJy4uLy4uL3BsYXRmb3JtX2Jyb3dzZXIvcmVjYXB0Y2hhL3JlY2FwdGNoYV9lbnRlcnByaXNlX3ZlcmlmaWVyJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7XG4gIFJlY2FwdGNoYUFjdGlvbk5hbWUsXG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYUF1dGhQcm92aWRlclxufSBmcm9tICcuLi8uLi9hcGknO1xuaW1wb3J0IHsgX2lzRmlyZWJhc2VTZXJ2ZXJBcHAgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBwYXNzd29yZCBwb2xpY3kgY2FjaGVkIGluIHRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UgaWYgYSBwb2xpY3kgaXMgYWxyZWFkeVxuICogY2FjaGVkIGZvciB0aGUgcHJvamVjdCBvciB0ZW5hbnQuXG4gKlxuICogQHJlbWFya3NcbiAqIFdlIG9ubHkgZmV0Y2ggdGhlIHBhc3N3b3JkIHBvbGljeSBpZiB0aGUgcGFzc3dvcmQgZGlkIG5vdCBtZWV0IHBvbGljeSByZXF1aXJlbWVudHMgYW5kXG4gKiB0aGVyZSBpcyBhbiBleGlzdGluZyBwb2xpY3kgY2FjaGVkLiBBIGRldmVsb3BlciBtdXN0IGNhbGwgdmFsaWRhdGVQYXNzd29yZCBhdCBsZWFzdFxuICogb25jZSBmb3IgdGhlIGNhY2hlIHRvIGJlIGF1dG9tYXRpY2FsbHkgdXBkYXRlZC5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVjYWNoZVBhc3N3b3JkUG9saWN5KGF1dGg6IEF1dGgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICBpZiAoYXV0aEludGVybmFsLl9nZXRQYXNzd29yZFBvbGljeUludGVybmFsKCkpIHtcbiAgICBhd2FpdCBhdXRoSW50ZXJuYWwuX3VwZGF0ZVBhc3N3b3JkUG9saWN5KCk7XG4gIH1cbn1cblxuLyoqXG4gKiBTZW5kcyBhIHBhc3N3b3JkIHJlc2V0IGVtYWlsIHRvIHRoZSBnaXZlbiBlbWFpbCBhZGRyZXNzLiBUaGlzIG1ldGhvZCBkb2VzIG5vdCB0aHJvdyBhbiBlcnJvciB3aGVuXG4gKiB0aGVyZSdzIG5vIHVzZXIgYWNjb3VudCB3aXRoIHRoZSBnaXZlbiBlbWFpbCBhZGRyZXNzIGFuZFxuICoge0BsaW5rIGh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9pZGVudGl0eS1wbGF0Zm9ybS9kb2NzL2FkbWluL2VtYWlsLWVudW1lcmF0aW9uLXByb3RlY3Rpb24gfCBFbWFpbCBFbnVtZXJhdGlvbiBQcm90ZWN0aW9ufVxuICogaXMgZW5hYmxlZC5cbiAqXG4gKiBAcmVtYXJrc1xuICogVG8gY29tcGxldGUgdGhlIHBhc3N3b3JkIHJlc2V0LCBjYWxsIHtAbGluayBjb25maXJtUGFzc3dvcmRSZXNldH0gd2l0aCB0aGUgY29kZSBzdXBwbGllZCBpblxuICogdGhlIGVtYWlsIHNlbnQgdG8gdGhlIHVzZXIsIGFsb25nIHdpdGggdGhlIG5ldyBwYXNzd29yZCBzcGVjaWZpZWQgYnkgdGhlIHVzZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGNvbnN0IGFjdGlvbkNvZGVTZXR0aW5ncyA9IHtcbiAqICAgdXJsOiAnaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vP2VtYWlsPXVzZXJAZXhhbXBsZS5jb20nLFxuICogICBpT1M6IHtcbiAqICAgICAgYnVuZGxlSWQ6ICdjb20uZXhhbXBsZS5pb3MnXG4gKiAgIH0sXG4gKiAgIGFuZHJvaWQ6IHtcbiAqICAgICBwYWNrYWdlTmFtZTogJ2NvbS5leGFtcGxlLmFuZHJvaWQnLFxuICogICAgIGluc3RhbGxBcHA6IHRydWUsXG4gKiAgICAgbWluaW11bVZlcnNpb246ICcxMidcbiAqICAgfSxcbiAqICAgaGFuZGxlQ29kZUluQXBwOiB0cnVlXG4gKiB9O1xuICogYXdhaXQgc2VuZFBhc3N3b3JkUmVzZXRFbWFpbChhdXRoLCAndXNlckBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gY29kZSBmcm9tIHVzZXIuXG4gKiBhd2FpdCBjb25maXJtUGFzc3dvcmRSZXNldCgndXNlckBleGFtcGxlLmNvbScsIGNvZGUpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVtYWlsIC0gVGhlIHVzZXIncyBlbWFpbCBhZGRyZXNzLlxuICogQHBhcmFtIGFjdGlvbkNvZGVTZXR0aW5ncyAtIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVNldHRpbmdzfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kUGFzc3dvcmRSZXNldEVtYWlsKFxuICBhdXRoOiBBdXRoLFxuICBlbWFpbDogc3RyaW5nLFxuICBhY3Rpb25Db2RlU2V0dGluZ3M/OiBBY3Rpb25Db2RlU2V0dGluZ3Ncbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBhdXRoSW50ZXJuYWwgPSBfY2FzdEF1dGgoYXV0aCk7XG4gIGNvbnN0IHJlcXVlc3Q6IGF1dGhlbnRpY2F0aW9uLlBhc3N3b3JkUmVzZXRSZXF1ZXN0ID0ge1xuICAgIHJlcXVlc3RUeXBlOiBBY3Rpb25Db2RlT3BlcmF0aW9uLlBBU1NXT1JEX1JFU0VULFxuICAgIGVtYWlsLFxuICAgIGNsaWVudFR5cGU6IFJlY2FwdGNoYUNsaWVudFR5cGUuV0VCXG4gIH07XG4gIGlmIChhY3Rpb25Db2RlU2V0dGluZ3MpIHtcbiAgICBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0KGF1dGhJbnRlcm5hbCwgcmVxdWVzdCwgYWN0aW9uQ29kZVNldHRpbmdzKTtcbiAgfVxuICBhd2FpdCBoYW5kbGVSZWNhcHRjaGFGbG93KFxuICAgIGF1dGhJbnRlcm5hbCxcbiAgICByZXF1ZXN0LFxuICAgIFJlY2FwdGNoYUFjdGlvbk5hbWUuR0VUX09PQl9DT0RFLFxuICAgIGF1dGhlbnRpY2F0aW9uLnNlbmRQYXNzd29yZFJlc2V0RW1haWwsXG4gICAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyLkVNQUlMX1BBU1NXT1JEX1BST1ZJREVSXG4gICk7XG59XG5cbi8qKlxuICogQ29tcGxldGVzIHRoZSBwYXNzd29yZCByZXNldCBwcm9jZXNzLCBnaXZlbiBhIGNvbmZpcm1hdGlvbiBjb2RlIGFuZCBuZXcgcGFzc3dvcmQuXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIG9vYkNvZGUgLSBBIGNvbmZpcm1hdGlvbiBjb2RlIHNlbnQgdG8gdGhlIHVzZXIuXG4gKiBAcGFyYW0gbmV3UGFzc3dvcmQgLSBUaGUgbmV3IHBhc3N3b3JkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbmZpcm1QYXNzd29yZFJlc2V0KFxuICBhdXRoOiBBdXRoLFxuICBvb2JDb2RlOiBzdHJpbmcsXG4gIG5ld1Bhc3N3b3JkOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBhY2NvdW50XG4gICAgLnJlc2V0UGFzc3dvcmQoZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpLCB7XG4gICAgICBvb2JDb2RlLFxuICAgICAgbmV3UGFzc3dvcmRcbiAgICB9KVxuICAgIC5jYXRjaChhc3luYyBlcnJvciA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGVycm9yLmNvZGUgPT09XG4gICAgICAgIGBhdXRoLyR7QXV0aEVycm9yQ29kZS5QQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UU31gXG4gICAgICApIHtcbiAgICAgICAgdm9pZCByZWNhY2hlUGFzc3dvcmRQb2xpY3koYXV0aCk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xuICAvLyBEbyBub3QgcmV0dXJuIHRoZSBlbWFpbC5cbn1cblxuLyoqXG4gKiBBcHBsaWVzIGEgdmVyaWZpY2F0aW9uIGNvZGUgc2VudCB0byB0aGUgdXNlciBieSBlbWFpbCBvciBvdGhlciBvdXQtb2YtYmFuZCBtZWNoYW5pc20uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIG9vYkNvZGUgLSBBIHZlcmlmaWNhdGlvbiBjb2RlIHNlbnQgdG8gdGhlIHVzZXIuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXBwbHlBY3Rpb25Db2RlKFxuICBhdXRoOiBBdXRoLFxuICBvb2JDb2RlOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBhY2NvdW50LmFwcGx5QWN0aW9uQ29kZShnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksIHsgb29iQ29kZSB9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSB2ZXJpZmljYXRpb24gY29kZSBzZW50IHRvIHRoZSB1c2VyIGJ5IGVtYWlsIG9yIG90aGVyIG91dC1vZi1iYW5kIG1lY2hhbmlzbS5cbiAqXG4gKiBAcmV0dXJucyBtZXRhZGF0YSBhYm91dCB0aGUgY29kZS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gb29iQ29kZSAtIEEgdmVyaWZpY2F0aW9uIGNvZGUgc2VudCB0byB0aGUgdXNlci5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja0FjdGlvbkNvZGUoXG4gIGF1dGg6IEF1dGgsXG4gIG9vYkNvZGU6IHN0cmluZ1xuKTogUHJvbWlzZTxBY3Rpb25Db2RlSW5mbz4ge1xuICBjb25zdCBhdXRoTW9kdWxhciA9IGdldE1vZHVsYXJJbnN0YW5jZShhdXRoKTtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhY2NvdW50LnJlc2V0UGFzc3dvcmQoYXV0aE1vZHVsYXIsIHsgb29iQ29kZSB9KTtcblxuICAvLyBFbWFpbCBjb3VsZCBiZSBlbXB0eSBvbmx5IGlmIHRoZSByZXF1ZXN0IHR5cGUgaXMgRU1BSUxfU0lHTklOIG9yXG4gIC8vIFZFUklGWV9BTkRfQ0hBTkdFX0VNQUlMLlxuICAvLyBOZXcgZW1haWwgc2hvdWxkIG5vdCBiZSBlbXB0eSBpZiB0aGUgcmVxdWVzdCB0eXBlIGlzXG4gIC8vIFZFUklGWV9BTkRfQ0hBTkdFX0VNQUlMLlxuICAvLyBNdWx0aS1mYWN0b3IgaW5mbyBjb3VsZCBub3QgYmUgZW1wdHkgaWYgdGhlIHJlcXVlc3QgdHlwZSBpc1xuICAvLyBSRVZFUlRfU0VDT05EX0ZBQ1RPUl9BRERJVElPTi5cbiAgY29uc3Qgb3BlcmF0aW9uID0gcmVzcG9uc2UucmVxdWVzdFR5cGU7XG4gIF9hc3NlcnQob3BlcmF0aW9uLCBhdXRoTW9kdWxhciwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gIHN3aXRjaCAob3BlcmF0aW9uKSB7XG4gICAgY2FzZSBBY3Rpb25Db2RlT3BlcmF0aW9uLkVNQUlMX1NJR05JTjpcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfQU5EX0NIQU5HRV9FTUFJTDpcbiAgICAgIF9hc3NlcnQocmVzcG9uc2UubmV3RW1haWwsIGF1dGhNb2R1bGFyLCBBdXRoRXJyb3JDb2RlLklOVEVSTkFMX0VSUk9SKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQWN0aW9uQ29kZU9wZXJhdGlvbi5SRVZFUlRfU0VDT05EX0ZBQ1RPUl9BRERJVElPTjpcbiAgICAgIF9hc3NlcnQocmVzcG9uc2UubWZhSW5mbywgYXV0aE1vZHVsYXIsIEF1dGhFcnJvckNvZGUuSU5URVJOQUxfRVJST1IpO1xuICAgIC8vIGZhbGwgdGhyb3VnaFxuICAgIGRlZmF1bHQ6XG4gICAgICBfYXNzZXJ0KHJlc3BvbnNlLmVtYWlsLCBhdXRoTW9kdWxhciwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gIH1cblxuICAvLyBUaGUgbXVsdGktZmFjdG9yIGluZm8gZm9yIHJldmVydCBzZWNvbmQgZmFjdG9yIGFkZGl0aW9uXG4gIGxldCBtdWx0aUZhY3RvckluZm86IE11bHRpRmFjdG9ySW5mb0ltcGwgfCBudWxsID0gbnVsbDtcbiAgaWYgKHJlc3BvbnNlLm1mYUluZm8pIHtcbiAgICBtdWx0aUZhY3RvckluZm8gPSBNdWx0aUZhY3RvckluZm9JbXBsLl9mcm9tU2VydmVyUmVzcG9uc2UoXG4gICAgICBfY2FzdEF1dGgoYXV0aE1vZHVsYXIpLFxuICAgICAgcmVzcG9uc2UubWZhSW5mb1xuICAgICk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGRhdGE6IHtcbiAgICAgIGVtYWlsOlxuICAgICAgICAocmVzcG9uc2UucmVxdWVzdFR5cGUgPT09IEFjdGlvbkNvZGVPcGVyYXRpb24uVkVSSUZZX0FORF9DSEFOR0VfRU1BSUxcbiAgICAgICAgICA/IHJlc3BvbnNlLm5ld0VtYWlsXG4gICAgICAgICAgOiByZXNwb25zZS5lbWFpbCkgfHwgbnVsbCxcbiAgICAgIHByZXZpb3VzRW1haWw6XG4gICAgICAgIChyZXNwb25zZS5yZXF1ZXN0VHlwZSA9PT0gQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfQU5EX0NIQU5HRV9FTUFJTFxuICAgICAgICAgID8gcmVzcG9uc2UuZW1haWxcbiAgICAgICAgICA6IHJlc3BvbnNlLm5ld0VtYWlsKSB8fCBudWxsLFxuICAgICAgbXVsdGlGYWN0b3JJbmZvXG4gICAgfSxcbiAgICBvcGVyYXRpb25cbiAgfTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSBwYXNzd29yZCByZXNldCBjb2RlIHNlbnQgdG8gdGhlIHVzZXIgYnkgZW1haWwgb3Igb3RoZXIgb3V0LW9mLWJhbmQgbWVjaGFuaXNtLlxuICpcbiAqIEByZXR1cm5zIHRoZSB1c2VyJ3MgZW1haWwgYWRkcmVzcyBpZiB2YWxpZC5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gY29kZSAtIEEgdmVyaWZpY2F0aW9uIGNvZGUgc2VudCB0byB0aGUgdXNlci5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlQYXNzd29yZFJlc2V0Q29kZShcbiAgYXV0aDogQXV0aCxcbiAgY29kZTogc3RyaW5nXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IGNoZWNrQWN0aW9uQ29kZShnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksIGNvZGUpO1xuICAvLyBFbWFpbCBzaG91bGQgYWx3YXlzIGJlIHByZXNlbnQgc2luY2UgYSBjb2RlIHdhcyBzZW50IHRvIGl0XG4gIHJldHVybiBkYXRhLmVtYWlsITtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHVzZXIgYWNjb3VudCBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBlbWFpbCBhZGRyZXNzIGFuZCBwYXNzd29yZC5cbiAqXG4gKiBAcmVtYXJrc1xuICogT24gc3VjY2Vzc2Z1bCBjcmVhdGlvbiBvZiB0aGUgdXNlciBhY2NvdW50LCB0aGlzIHVzZXIgd2lsbCBhbHNvIGJlIHNpZ25lZCBpbiB0byB5b3VyIGFwcGxpY2F0aW9uLlxuICpcbiAqIFVzZXIgYWNjb3VudCBjcmVhdGlvbiBjYW4gZmFpbCBpZiB0aGUgYWNjb3VudCBhbHJlYWR5IGV4aXN0cyBvciB0aGUgcGFzc3dvcmQgaXMgaW52YWxpZC5cbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIG9uIHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBOb3RlOiBUaGUgZW1haWwgYWRkcmVzcyBhY3RzIGFzIGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSB1c2VyIGFuZCBlbmFibGVzIGFuIGVtYWlsLWJhc2VkXG4gKiBwYXNzd29yZCByZXNldC4gVGhpcyBmdW5jdGlvbiB3aWxsIGNyZWF0ZSBhIG5ldyB1c2VyIGFjY291bnQgYW5kIHNldCB0aGUgaW5pdGlhbCB1c2VyIHBhc3N3b3JkLlxuICpcbiAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqIEBwYXJhbSBlbWFpbCAtIFRoZSB1c2VyJ3MgZW1haWwgYWRkcmVzcy5cbiAqIEBwYXJhbSBwYXNzd29yZCAtIFRoZSB1c2VyJ3MgY2hvc2VuIHBhc3N3b3JkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZyxcbiAgcGFzc3dvcmQ6IHN0cmluZ1xuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAoYXV0aC5hcHApKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IoYXV0aClcbiAgICApO1xuICB9XG4gIGNvbnN0IGF1dGhJbnRlcm5hbCA9IF9jYXN0QXV0aChhdXRoKTtcbiAgY29uc3QgcmVxdWVzdDogU2lnblVwUmVxdWVzdCA9IHtcbiAgICByZXR1cm5TZWN1cmVUb2tlbjogdHJ1ZSxcbiAgICBlbWFpbCxcbiAgICBwYXNzd29yZCxcbiAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICB9O1xuICBjb25zdCBzaWduVXBSZXNwb25zZTogUHJvbWlzZTxJZFRva2VuUmVzcG9uc2U+ID0gaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgcmVxdWVzdCxcbiAgICBSZWNhcHRjaGFBY3Rpb25OYW1lLlNJR05fVVBfUEFTU1dPUkQsXG4gICAgc2lnblVwLFxuICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICApO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHNpZ25VcFJlc3BvbnNlLmNhdGNoKGVycm9yID0+IHtcbiAgICBpZiAoXG4gICAgICBlcnJvci5jb2RlID09PSBgYXV0aC8ke0F1dGhFcnJvckNvZGUuUEFTU1dPUkRfRE9FU19OT1RfTUVFVF9SRVFVSVJFTUVOVFN9YFxuICAgICkge1xuICAgICAgdm9pZCByZWNhY2hlUGFzc3dvcmRQb2xpY3koYXV0aCk7XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyb3I7XG4gIH0pO1xuXG4gIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgVXNlckNyZWRlbnRpYWxJbXBsLl9mcm9tSWRUb2tlblJlc3BvbnNlKFxuICAgIGF1dGhJbnRlcm5hbCxcbiAgICBPcGVyYXRpb25UeXBlLlNJR05fSU4sXG4gICAgcmVzcG9uc2VcbiAgKTtcbiAgYXdhaXQgYXV0aEludGVybmFsLl91cGRhdGVDdXJyZW50VXNlcih1c2VyQ3JlZGVudGlhbC51c2VyKTtcblxuICByZXR1cm4gdXNlckNyZWRlbnRpYWw7XG59XG5cbi8qKlxuICogQXN5bmNocm9ub3VzbHkgc2lnbnMgaW4gdXNpbmcgYW4gZW1haWwgYW5kIHBhc3N3b3JkLlxuICpcbiAqIEByZW1hcmtzXG4gKiBGYWlscyB3aXRoIGFuIGVycm9yIGlmIHRoZSBlbWFpbCBhZGRyZXNzIGFuZCBwYXNzd29yZCBkbyBub3QgbWF0Y2guIFdoZW5cbiAqIHtAbGluayBodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWRlbnRpdHktcGxhdGZvcm0vZG9jcy9hZG1pbi9lbWFpbC1lbnVtZXJhdGlvbi1wcm90ZWN0aW9uIHwgRW1haWwgRW51bWVyYXRpb24gUHJvdGVjdGlvbn1cbiAqIGlzIGVuYWJsZWQsIHRoaXMgbWV0aG9kIGZhaWxzIHdpdGggXCJhdXRoL2ludmFsaWQtY3JlZGVudGlhbFwiIGluIGNhc2Ugb2YgYW4gaW52YWxpZFxuICogZW1haWwvcGFzc3dvcmQuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBvbiB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogTm90ZTogVGhlIHVzZXIncyBwYXNzd29yZCBpcyBOT1QgdGhlIHBhc3N3b3JkIHVzZWQgdG8gYWNjZXNzIHRoZSB1c2VyJ3MgZW1haWwgYWNjb3VudC4gVGhlXG4gKiBlbWFpbCBhZGRyZXNzIHNlcnZlcyBhcyBhIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgdXNlciwgYW5kIHRoZSBwYXNzd29yZCBpcyB1c2VkIHRvIGFjY2Vzc1xuICogdGhlIHVzZXIncyBhY2NvdW50IGluIHlvdXIgRmlyZWJhc2UgcHJvamVjdC4gU2VlIGFsc286IHtAbGluayBjcmVhdGVVc2VyV2l0aEVtYWlsQW5kUGFzc3dvcmR9LlxuICpcbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gZW1haWwgLSBUaGUgdXNlcnMgZW1haWwgYWRkcmVzcy5cbiAqIEBwYXJhbSBwYXNzd29yZCAtIFRoZSB1c2VycyBwYXNzd29yZC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduSW5XaXRoRW1haWxBbmRQYXNzd29yZChcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZyxcbiAgcGFzc3dvcmQ6IHN0cmluZ1xuKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAoYXV0aC5hcHApKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KFxuICAgICAgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IoYXV0aClcbiAgICApO1xuICB9XG4gIHJldHVybiBzaWduSW5XaXRoQ3JlZGVudGlhbChcbiAgICBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksXG4gICAgRW1haWxBdXRoUHJvdmlkZXIuY3JlZGVudGlhbChlbWFpbCwgcGFzc3dvcmQpXG4gICkuY2F0Y2goYXN5bmMgZXJyb3IgPT4ge1xuICAgIGlmIChcbiAgICAgIGVycm9yLmNvZGUgPT09IGBhdXRoLyR7QXV0aEVycm9yQ29kZS5QQVNTV09SRF9ET0VTX05PVF9NRUVUX1JFUVVJUkVNRU5UU31gXG4gICAgKSB7XG4gICAgICB2b2lkIHJlY2FjaGVQYXNzd29yZFBvbGljeShhdXRoKTtcbiAgICB9XG5cbiAgICB0aHJvdyBlcnJvcjtcbiAgfSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgQWN0aW9uQ29kZU9wZXJhdGlvbixcbiAgQWN0aW9uQ29kZVNldHRpbmdzLFxuICBBdXRoLFxuICBVc2VyQ3JlZGVudGlhbFxufSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQgKiBhcyBhcGkgZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBBY3Rpb25Db2RlVVJMIH0gZnJvbSAnLi4vYWN0aW9uX2NvZGVfdXJsJztcbmltcG9ydCB7IEVtYWlsQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi4vcHJvdmlkZXJzL2VtYWlsJztcbmltcG9ydCB7IF9nZXRDdXJyZW50VXJsIH0gZnJvbSAnLi4vdXRpbC9sb2NhdGlvbic7XG5pbXBvcnQgeyBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0IH0gZnJvbSAnLi9hY3Rpb25fY29kZV9zZXR0aW5ncyc7XG5pbXBvcnQgeyBzaWduSW5XaXRoQ3JlZGVudGlhbCB9IGZyb20gJy4vY3JlZGVudGlhbCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBfY2FzdEF1dGggfSBmcm9tICcuLi9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgeyBoYW5kbGVSZWNhcHRjaGFGbG93IH0gZnJvbSAnLi4vLi4vcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXInO1xuaW1wb3J0IHtcbiAgUmVjYXB0Y2hhQWN0aW9uTmFtZSxcbiAgUmVjYXB0Y2hhQ2xpZW50VHlwZSxcbiAgUmVjYXB0Y2hhQXV0aFByb3ZpZGVyXG59IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQgeyBfaXNGaXJlYmFzZVNlcnZlckFwcCB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IgfSBmcm9tICcuLi8uLi9jb3JlL3V0aWwvYXNzZXJ0JztcblxuLyoqXG4gKiBTZW5kcyBhIHNpZ24taW4gZW1haWwgbGluayB0byB0aGUgdXNlciB3aXRoIHRoZSBzcGVjaWZpZWQgZW1haWwuXG4gKlxuICogQHJlbWFya3NcbiAqIFRoZSBzaWduLWluIG9wZXJhdGlvbiBoYXMgdG8gYWx3YXlzIGJlIGNvbXBsZXRlZCBpbiB0aGUgYXBwIHVubGlrZSBvdGhlciBvdXQgb2YgYmFuZCBlbWFpbFxuICogYWN0aW9ucyAocGFzc3dvcmQgcmVzZXQgYW5kIGVtYWlsIHZlcmlmaWNhdGlvbnMpLiBUaGlzIGlzIGJlY2F1c2UsIGF0IHRoZSBlbmQgb2YgdGhlIGZsb3csXG4gKiB0aGUgdXNlciBpcyBleHBlY3RlZCB0byBiZSBzaWduZWQgaW4gYW5kIHRoZWlyIEF1dGggc3RhdGUgcGVyc2lzdGVkIHdpdGhpbiB0aGUgYXBwLlxuICpcbiAqIFRvIGNvbXBsZXRlIHNpZ24gaW4gd2l0aCB0aGUgZW1haWwgbGluaywgY2FsbCB7QGxpbmsgc2lnbkluV2l0aEVtYWlsTGlua30gd2l0aCB0aGUgZW1haWxcbiAqIGFkZHJlc3MgYW5kIHRoZSBlbWFpbCBsaW5rIHN1cHBsaWVkIGluIHRoZSBlbWFpbCBzZW50IHRvIHRoZSB1c2VyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHNlbmRTaWduSW5MaW5rVG9FbWFpbChhdXRoLCAndXNlckBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gZW1haWxMaW5rIGZyb20gdGhlIHVzZXIuXG4gKiBpZihpc1NpZ25JbldpdGhFbWFpbExpbmsoYXV0aCwgZW1haWxMaW5rKSkge1xuICogICBhd2FpdCBzaWduSW5XaXRoRW1haWxMaW5rKGF1dGgsICd1c2VyQGV4YW1wbGUuY29tJywgZW1haWxMaW5rKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBhdXRoSW50ZXJuYWwgLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVtYWlsIC0gVGhlIHVzZXIncyBlbWFpbCBhZGRyZXNzLlxuICogQHBhcmFtIGFjdGlvbkNvZGVTZXR0aW5ncyAtIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVNldHRpbmdzfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kU2lnbkluTGlua1RvRW1haWwoXG4gIGF1dGg6IEF1dGgsXG4gIGVtYWlsOiBzdHJpbmcsXG4gIGFjdGlvbkNvZGVTZXR0aW5nczogQWN0aW9uQ29kZVNldHRpbmdzXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICBjb25zdCByZXF1ZXN0OiBhcGkuRW1haWxTaWduSW5SZXF1ZXN0ID0ge1xuICAgIHJlcXVlc3RUeXBlOiBBY3Rpb25Db2RlT3BlcmF0aW9uLkVNQUlMX1NJR05JTixcbiAgICBlbWFpbCxcbiAgICBjbGllbnRUeXBlOiBSZWNhcHRjaGFDbGllbnRUeXBlLldFQlxuICB9O1xuICBmdW5jdGlvbiBzZXRBY3Rpb25Db2RlU2V0dGluZ3MoXG4gICAgcmVxdWVzdDogYXBpLkVtYWlsU2lnbkluUmVxdWVzdCxcbiAgICBhY3Rpb25Db2RlU2V0dGluZ3M6IEFjdGlvbkNvZGVTZXR0aW5nc1xuICApOiB2b2lkIHtcbiAgICBfYXNzZXJ0KFxuICAgICAgYWN0aW9uQ29kZVNldHRpbmdzLmhhbmRsZUNvZGVJbkFwcCxcbiAgICAgIGF1dGhJbnRlcm5hbCxcbiAgICAgIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JcbiAgICApO1xuICAgIGlmIChhY3Rpb25Db2RlU2V0dGluZ3MpIHtcbiAgICAgIF9zZXRBY3Rpb25Db2RlU2V0dGluZ3NPblJlcXVlc3QoXG4gICAgICAgIGF1dGhJbnRlcm5hbCxcbiAgICAgICAgcmVxdWVzdCxcbiAgICAgICAgYWN0aW9uQ29kZVNldHRpbmdzXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBzZXRBY3Rpb25Db2RlU2V0dGluZ3MocmVxdWVzdCwgYWN0aW9uQ29kZVNldHRpbmdzKTtcbiAgYXdhaXQgaGFuZGxlUmVjYXB0Y2hhRmxvdyhcbiAgICBhdXRoSW50ZXJuYWwsXG4gICAgcmVxdWVzdCxcbiAgICBSZWNhcHRjaGFBY3Rpb25OYW1lLkdFVF9PT0JfQ09ERSxcbiAgICBhcGkuc2VuZFNpZ25JbkxpbmtUb0VtYWlsLFxuICAgIFJlY2FwdGNoYUF1dGhQcm92aWRlci5FTUFJTF9QQVNTV09SRF9QUk9WSURFUlxuICApO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBpbmNvbWluZyBsaW5rIGlzIGEgc2lnbi1pbiB3aXRoIGVtYWlsIGxpbmsgc3VpdGFibGUgZm9yIHtAbGluayBzaWduSW5XaXRoRW1haWxMaW5rfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gZW1haWxMaW5rIC0gVGhlIGxpbmsgc2VudCB0byB0aGUgdXNlcidzIGVtYWlsIGFkZHJlc3MuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTaWduSW5XaXRoRW1haWxMaW5rKGF1dGg6IEF1dGgsIGVtYWlsTGluazogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IGFjdGlvbkNvZGVVcmwgPSBBY3Rpb25Db2RlVVJMLnBhcnNlTGluayhlbWFpbExpbmspO1xuICByZXR1cm4gYWN0aW9uQ29kZVVybD8ub3BlcmF0aW9uID09PSBBY3Rpb25Db2RlT3BlcmF0aW9uLkVNQUlMX1NJR05JTjtcbn1cblxuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzaWducyBpbiB1c2luZyBhbiBlbWFpbCBhbmQgc2lnbi1pbiBlbWFpbCBsaW5rLlxuICpcbiAqIEByZW1hcmtzXG4gKiBJZiBubyBsaW5rIGlzIHBhc3NlZCwgdGhlIGxpbmsgaXMgaW5mZXJyZWQgZnJvbSB0aGUgY3VycmVudCBVUkwuXG4gKlxuICogRmFpbHMgd2l0aCBhbiBlcnJvciBpZiB0aGUgZW1haWwgYWRkcmVzcyBpcyBpbnZhbGlkIG9yIE9UUCBpbiBlbWFpbCBsaW5rIGV4cGlyZXMuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogTm90ZTogQ29uZmlybSB0aGUgbGluayBpcyBhIHNpZ24taW4gZW1haWwgbGluayBiZWZvcmUgY2FsbGluZyB0aGlzIG1ldGhvZCBmaXJlYmFzZS5hdXRoLkF1dGguaXNTaWduSW5XaXRoRW1haWxMaW5rLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHNlbmRTaWduSW5MaW5rVG9FbWFpbChhdXRoLCAndXNlckBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gZW1haWxMaW5rIGZyb20gdGhlIHVzZXIuXG4gKiBpZihpc1NpZ25JbldpdGhFbWFpbExpbmsoYXV0aCwgZW1haWxMaW5rKSkge1xuICogICBhd2FpdCBzaWduSW5XaXRoRW1haWxMaW5rKGF1dGgsICd1c2VyQGV4YW1wbGUuY29tJywgZW1haWxMaW5rKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gZW1haWwgLSBUaGUgdXNlcidzIGVtYWlsIGFkZHJlc3MuXG4gKiBAcGFyYW0gZW1haWxMaW5rIC0gVGhlIGxpbmsgc2VudCB0byB0aGUgdXNlcidzIGVtYWlsIGFkZHJlc3MuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluV2l0aEVtYWlsTGluayhcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZyxcbiAgZW1haWxMaW5rPzogc3RyaW5nXG4pOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gIGlmIChfaXNGaXJlYmFzZVNlcnZlckFwcChhdXRoLmFwcCkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoXG4gICAgICBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvcihhdXRoKVxuICAgICk7XG4gIH1cbiAgY29uc3QgYXV0aE1vZHVsYXIgPSBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCk7XG4gIGNvbnN0IGNyZWRlbnRpYWwgPSBFbWFpbEF1dGhQcm92aWRlci5jcmVkZW50aWFsV2l0aExpbmsoXG4gICAgZW1haWwsXG4gICAgZW1haWxMaW5rIHx8IF9nZXRDdXJyZW50VXJsKClcbiAgKTtcbiAgLy8gQ2hlY2sgaWYgdGhlIHRlbmFudCBJRCBpbiB0aGUgZW1haWwgbGluayBtYXRjaGVzIHRoZSB0ZW5hbnQgSUQgb24gQXV0aFxuICAvLyBpbnN0YW5jZS5cbiAgX2Fzc2VydChcbiAgICBjcmVkZW50aWFsLl90ZW5hbnRJZCA9PT0gKGF1dGhNb2R1bGFyLnRlbmFudElkIHx8IG51bGwpLFxuICAgIGF1dGhNb2R1bGFyLFxuICAgIEF1dGhFcnJvckNvZGUuVEVOQU5UX0lEX01JU01BVENIXG4gICk7XG4gIHJldHVybiBzaWduSW5XaXRoQ3JlZGVudGlhbChhdXRoTW9kdWxhciwgY3JlZGVudGlhbCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeSxcbiAgX3BlcmZvcm1BcGlSZXF1ZXN0XG59IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7IEF1dGggfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUF1dGhVcmlSZXF1ZXN0IHtcbiAgaWRlbnRpZmllcjogc3RyaW5nO1xuICBjb250aW51ZVVyaTogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBdXRoVXJpUmVzcG9uc2Uge1xuICBzaWduaW5NZXRob2RzOiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUF1dGhVcmkoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IENyZWF0ZUF1dGhVcmlSZXF1ZXN0XG4pOiBQcm9taXNlPENyZWF0ZUF1dGhVcmlSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PENyZWF0ZUF1dGhVcmlSZXF1ZXN0LCBDcmVhdGVBdXRoVXJpUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LkNSRUFURV9BVVRIX1VSSSxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICBBY3Rpb25Db2RlT3BlcmF0aW9uLFxuICBBY3Rpb25Db2RlU2V0dGluZ3MsXG4gIEF1dGgsXG4gIFVzZXJcbn0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHtcbiAgY3JlYXRlQXV0aFVyaSxcbiAgQ3JlYXRlQXV0aFVyaVJlcXVlc3Rcbn0gZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2NyZWF0ZV9hdXRoX3VyaSc7XG5pbXBvcnQgKiBhcyBhcGkgZnJvbSAnLi4vLi4vYXBpL2F1dGhlbnRpY2F0aW9uL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IF9nZXRDdXJyZW50VXJsLCBfaXNIdHRwT3JIdHRwcyB9IGZyb20gJy4uL3V0aWwvbG9jYXRpb24nO1xuaW1wb3J0IHsgX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdCB9IGZyb20gJy4vYWN0aW9uX2NvZGVfc2V0dGluZ3MnO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG4vKipcbiAqIEdldHMgdGhlIGxpc3Qgb2YgcG9zc2libGUgc2lnbiBpbiBtZXRob2RzIGZvciB0aGUgZ2l2ZW4gZW1haWwgYWRkcmVzcy4gVGhpcyBtZXRob2QgcmV0dXJucyBhblxuICogZW1wdHkgbGlzdCB3aGVuXG4gKiB7QGxpbmsgaHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL2lkZW50aXR5LXBsYXRmb3JtL2RvY3MvYWRtaW4vZW1haWwtZW51bWVyYXRpb24tcHJvdGVjdGlvbiB8IEVtYWlsIEVudW1lcmF0aW9uIFByb3RlY3Rpb259XG4gKiBpcyBlbmFibGVkLCBpcnJlc3BlY3RpdmUgb2YgdGhlIG51bWJlciBvZiBhdXRoZW50aWNhdGlvbiBtZXRob2RzIGF2YWlsYWJsZSBmb3IgdGhlIGdpdmVuIGVtYWlsLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGlzIHVzZWZ1bCB0byBkaWZmZXJlbnRpYXRlIG1ldGhvZHMgb2Ygc2lnbi1pbiBmb3IgdGhlIHNhbWUgcHJvdmlkZXIsIGVnLlxuICoge0BsaW5rIEVtYWlsQXV0aFByb3ZpZGVyfSB3aGljaCBoYXMgMiBtZXRob2RzIG9mIHNpZ24taW4sXG4gKiB7QGxpbmsgU2lnbkluTWV0aG9kfS5FTUFJTF9QQVNTV09SRCBhbmRcbiAqIHtAbGluayBTaWduSW5NZXRob2R9LkVNQUlMX0xJTksuXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVtYWlsIC0gVGhlIHVzZXIncyBlbWFpbCBhZGRyZXNzLlxuICpcbiAqIERlcHJlY2F0ZWQuIE1pZ3JhdGluZyBvZmYgb2YgdGhpcyBtZXRob2QgaXMgcmVjb21tZW5kZWQgYXMgYSBzZWN1cml0eSBiZXN0LXByYWN0aWNlLlxuICogTGVhcm4gbW9yZSBpbiB0aGUgSWRlbnRpdHkgUGxhdGZvcm0gZG9jdW1lbnRhdGlvbiBmb3JcbiAqIHtAbGluayBodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWRlbnRpdHktcGxhdGZvcm0vZG9jcy9hZG1pbi9lbWFpbC1lbnVtZXJhdGlvbi1wcm90ZWN0aW9uIHwgRW1haWwgRW51bWVyYXRpb24gUHJvdGVjdGlvbn0uXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChcbiAgYXV0aDogQXV0aCxcbiAgZW1haWw6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAvLyBjcmVhdGVBdXRoVXJpIHJldHVybnMgYW4gZXJyb3IgaWYgY29udGludWUgVVJJIGlzIG5vdCBodHRwIG9yIGh0dHBzLlxuICAvLyBGb3IgZW52aXJvbm1lbnRzIGxpa2UgQ29yZG92YSwgQ2hyb21lIGV4dGVuc2lvbnMsIG5hdGl2ZSBmcmFtZXdvcmtzLCBmaWxlXG4gIC8vIHN5c3RlbXMsIGV0YywgdXNlIGh0dHA6Ly9sb2NhbGhvc3QgYXMgY29udGludWUgVVJMLlxuICBjb25zdCBjb250aW51ZVVyaSA9IF9pc0h0dHBPckh0dHBzKCkgPyBfZ2V0Q3VycmVudFVybCgpIDogJ2h0dHA6Ly9sb2NhbGhvc3QnO1xuICBjb25zdCByZXF1ZXN0OiBDcmVhdGVBdXRoVXJpUmVxdWVzdCA9IHtcbiAgICBpZGVudGlmaWVyOiBlbWFpbCxcbiAgICBjb250aW51ZVVyaVxuICB9O1xuXG4gIGNvbnN0IHsgc2lnbmluTWV0aG9kcyB9ID0gYXdhaXQgY3JlYXRlQXV0aFVyaShcbiAgICBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCksXG4gICAgcmVxdWVzdFxuICApO1xuXG4gIHJldHVybiBzaWduaW5NZXRob2RzIHx8IFtdO1xufVxuXG4vKipcbiAqIFNlbmRzIGEgdmVyaWZpY2F0aW9uIGVtYWlsIHRvIGEgdXNlci5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhlIHZlcmlmaWNhdGlvbiBwcm9jZXNzIGlzIGNvbXBsZXRlZCBieSBjYWxsaW5nIHtAbGluayBhcHBseUFjdGlvbkNvZGV9LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHNlbmRFbWFpbFZlcmlmaWNhdGlvbih1c2VyLCBhY3Rpb25Db2RlU2V0dGluZ3MpO1xuICogLy8gT2J0YWluIGNvZGUgZnJvbSB0aGUgdXNlci5cbiAqIGF3YWl0IGFwcGx5QWN0aW9uQ29kZShhdXRoLCBjb2RlKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gYWN0aW9uQ29kZVNldHRpbmdzIC0gVGhlIHtAbGluayBBY3Rpb25Db2RlU2V0dGluZ3N9LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmRFbWFpbFZlcmlmaWNhdGlvbihcbiAgdXNlcjogVXNlcixcbiAgYWN0aW9uQ29kZVNldHRpbmdzPzogQWN0aW9uQ29kZVNldHRpbmdzIHwgbnVsbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbCA9IGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWw7XG4gIGNvbnN0IGlkVG9rZW4gPSBhd2FpdCB1c2VyLmdldElkVG9rZW4oKTtcbiAgY29uc3QgcmVxdWVzdDogYXBpLlZlcmlmeUVtYWlsUmVxdWVzdCA9IHtcbiAgICByZXF1ZXN0VHlwZTogQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfRU1BSUwsXG4gICAgaWRUb2tlblxuICB9O1xuICBpZiAoYWN0aW9uQ29kZVNldHRpbmdzKSB7XG4gICAgX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdChcbiAgICAgIHVzZXJJbnRlcm5hbC5hdXRoLFxuICAgICAgcmVxdWVzdCxcbiAgICAgIGFjdGlvbkNvZGVTZXR0aW5nc1xuICAgICk7XG4gIH1cblxuICBjb25zdCB7IGVtYWlsIH0gPSBhd2FpdCBhcGkuc2VuZEVtYWlsVmVyaWZpY2F0aW9uKHVzZXJJbnRlcm5hbC5hdXRoLCByZXF1ZXN0KTtcblxuICBpZiAoZW1haWwgIT09IHVzZXIuZW1haWwpIHtcbiAgICBhd2FpdCB1c2VyLnJlbG9hZCgpO1xuICB9XG59XG5cbi8qKlxuICogU2VuZHMgYSB2ZXJpZmljYXRpb24gZW1haWwgdG8gYSBuZXcgZW1haWwgYWRkcmVzcy5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhlIHVzZXIncyBlbWFpbCB3aWxsIGJlIHVwZGF0ZWQgdG8gdGhlIG5ldyBvbmUgYWZ0ZXIgYmVpbmcgdmVyaWZpZWQuXG4gKlxuICogSWYgeW91IGhhdmUgYSBjdXN0b20gZW1haWwgYWN0aW9uIGhhbmRsZXIsIHlvdSBjYW4gY29tcGxldGUgdGhlIHZlcmlmaWNhdGlvbiBwcm9jZXNzIGJ5IGNhbGxpbmdcbiAqIHtAbGluayBhcHBseUFjdGlvbkNvZGV9LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBhY3Rpb25Db2RlU2V0dGluZ3MgPSB7XG4gKiAgIHVybDogJ2h0dHBzOi8vd3d3LmV4YW1wbGUuY29tLz9lbWFpbD11c2VyQGV4YW1wbGUuY29tJyxcbiAqICAgaU9TOiB7XG4gKiAgICAgIGJ1bmRsZUlkOiAnY29tLmV4YW1wbGUuaW9zJ1xuICogICB9LFxuICogICBhbmRyb2lkOiB7XG4gKiAgICAgcGFja2FnZU5hbWU6ICdjb20uZXhhbXBsZS5hbmRyb2lkJyxcbiAqICAgICBpbnN0YWxsQXBwOiB0cnVlLFxuICogICAgIG1pbmltdW1WZXJzaW9uOiAnMTInXG4gKiAgIH0sXG4gKiAgIGhhbmRsZUNvZGVJbkFwcDogdHJ1ZVxuICogfTtcbiAqIGF3YWl0IHZlcmlmeUJlZm9yZVVwZGF0ZUVtYWlsKHVzZXIsICduZXdlbWFpbEBleGFtcGxlLmNvbScsIGFjdGlvbkNvZGVTZXR0aW5ncyk7XG4gKiAvLyBPYnRhaW4gY29kZSBmcm9tIHRoZSB1c2VyLlxuICogYXdhaXQgYXBwbHlBY3Rpb25Db2RlKGF1dGgsIGNvZGUpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHVzZXIgLSBUaGUgdXNlci5cbiAqIEBwYXJhbSBuZXdFbWFpbCAtIFRoZSBuZXcgZW1haWwgYWRkcmVzcyB0byBiZSB2ZXJpZmllZCBiZWZvcmUgdXBkYXRlLlxuICogQHBhcmFtIGFjdGlvbkNvZGVTZXR0aW5ncyAtIFRoZSB7QGxpbmsgQWN0aW9uQ29kZVNldHRpbmdzfS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlCZWZvcmVVcGRhdGVFbWFpbChcbiAgdXNlcjogVXNlcixcbiAgbmV3RW1haWw6IHN0cmluZyxcbiAgYWN0aW9uQ29kZVNldHRpbmdzPzogQWN0aW9uQ29kZVNldHRpbmdzIHwgbnVsbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHVzZXJJbnRlcm5hbCA9IGdldE1vZHVsYXJJbnN0YW5jZSh1c2VyKSBhcyBVc2VySW50ZXJuYWw7XG4gIGNvbnN0IGlkVG9rZW4gPSBhd2FpdCB1c2VyLmdldElkVG9rZW4oKTtcbiAgY29uc3QgcmVxdWVzdDogYXBpLlZlcmlmeUFuZENoYW5nZUVtYWlsUmVxdWVzdCA9IHtcbiAgICByZXF1ZXN0VHlwZTogQWN0aW9uQ29kZU9wZXJhdGlvbi5WRVJJRllfQU5EX0NIQU5HRV9FTUFJTCxcbiAgICBpZFRva2VuLFxuICAgIG5ld0VtYWlsXG4gIH07XG4gIGlmIChhY3Rpb25Db2RlU2V0dGluZ3MpIHtcbiAgICBfc2V0QWN0aW9uQ29kZVNldHRpbmdzT25SZXF1ZXN0KFxuICAgICAgdXNlckludGVybmFsLmF1dGgsXG4gICAgICByZXF1ZXN0LFxuICAgICAgYWN0aW9uQ29kZVNldHRpbmdzXG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHsgZW1haWwgfSA9IGF3YWl0IGFwaS52ZXJpZnlBbmRDaGFuZ2VFbWFpbCh1c2VySW50ZXJuYWwuYXV0aCwgcmVxdWVzdCk7XG5cbiAgaWYgKGVtYWlsICE9PSB1c2VyLmVtYWlsKSB7XG4gICAgLy8gSWYgdGhlIGxvY2FsIGNvcHkgb2YgdGhlIGVtYWlsIG9uIHVzZXIgaXMgb3V0ZGF0ZWQsIHJlbG9hZCB0aGVcbiAgICAvLyB1c2VyLlxuICAgIGF3YWl0IHVzZXIucmVsb2FkKCk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBFbmRwb2ludCwgSHR0cE1ldGhvZCwgX3BlcmZvcm1BcGlSZXF1ZXN0IH0gZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHsgSWRUb2tlblJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaWRfdG9rZW4nO1xuaW1wb3J0IHsgQXV0aCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlUHJvZmlsZVJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbDtcbiAgcGhvdG9Vcmw/OiBzdHJpbmcgfCBudWxsO1xuICByZXR1cm5TZWN1cmVUb2tlbjogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBVcGRhdGVQcm9maWxlUmVzcG9uc2UgZXh0ZW5kcyBJZFRva2VuUmVzcG9uc2Uge1xuICBkaXNwbGF5TmFtZT86IHN0cmluZyB8IG51bGw7XG4gIHBob3RvVXJsPzogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVByb2ZpbGUoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IFVwZGF0ZVByb2ZpbGVSZXF1ZXN0XG4pOiBQcm9taXNlPFVwZGF0ZVByb2ZpbGVSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFVwZGF0ZVByb2ZpbGVSZXF1ZXN0LCBVcGRhdGVQcm9maWxlUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNFVF9BQ0NPVU5UX0lORk8sXG4gICAgcmVxdWVzdFxuICApO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi8uLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQge1xuICB1cGRhdGVFbWFpbFBhc3N3b3JkIGFzIGFwaVVwZGF0ZUVtYWlsUGFzc3dvcmQsXG4gIFVwZGF0ZUVtYWlsUGFzc3dvcmRSZXF1ZXN0XG59IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvZW1haWxfYW5kX3Bhc3N3b3JkJztcbmltcG9ydCB7IHVwZGF0ZVByb2ZpbGUgYXMgYXBpVXBkYXRlUHJvZmlsZSB9IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvcHJvZmlsZSc7XG5pbXBvcnQgeyBVc2VySW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IF9sb2dvdXRJZkludmFsaWRhdGVkIH0gZnJvbSAnLi9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuaW1wb3J0IHsgUHJvdmlkZXJJZCB9IGZyb20gJy4uLy4uL21vZGVsL2VudW1zJztcbmltcG9ydCB7IF9pc0ZpcmViYXNlU2VydmVyQXBwIH0gZnJvbSAnQGZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBfc2VydmVyQXBwQ3VycmVudFVzZXJPcGVyYXRpb25Ob3RTdXBwb3J0ZWRFcnJvciB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIFVwZGF0ZXMgYSB1c2VyJ3MgcHJvZmlsZSBkYXRhLlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gcHJvZmlsZSAtIFRoZSBwcm9maWxlJ3MgYGRpc3BsYXlOYW1lYCBhbmQgYHBob3RvVVJMYCB0byB1cGRhdGUuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlUHJvZmlsZShcbiAgdXNlcjogVXNlcixcbiAge1xuICAgIGRpc3BsYXlOYW1lLFxuICAgIHBob3RvVVJMOiBwaG90b1VybFxuICB9OiB7IGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbDsgcGhvdG9VUkw/OiBzdHJpbmcgfCBudWxsIH1cbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoZGlzcGxheU5hbWUgPT09IHVuZGVmaW5lZCAmJiBwaG90b1VybCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgdXNlckludGVybmFsID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbDtcbiAgY29uc3QgaWRUb2tlbiA9IGF3YWl0IHVzZXJJbnRlcm5hbC5nZXRJZFRva2VuKCk7XG4gIGNvbnN0IHByb2ZpbGVSZXF1ZXN0ID0ge1xuICAgIGlkVG9rZW4sXG4gICAgZGlzcGxheU5hbWUsXG4gICAgcGhvdG9VcmwsXG4gICAgcmV0dXJuU2VjdXJlVG9rZW46IHRydWVcbiAgfTtcbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBfbG9nb3V0SWZJbnZhbGlkYXRlZChcbiAgICB1c2VySW50ZXJuYWwsXG4gICAgYXBpVXBkYXRlUHJvZmlsZSh1c2VySW50ZXJuYWwuYXV0aCwgcHJvZmlsZVJlcXVlc3QpXG4gICk7XG5cbiAgdXNlckludGVybmFsLmRpc3BsYXlOYW1lID0gcmVzcG9uc2UuZGlzcGxheU5hbWUgfHwgbnVsbDtcbiAgdXNlckludGVybmFsLnBob3RvVVJMID0gcmVzcG9uc2UucGhvdG9VcmwgfHwgbnVsbDtcblxuICAvLyBVcGRhdGUgdGhlIHBhc3N3b3JkIHByb3ZpZGVyIGFzIHdlbGxcbiAgY29uc3QgcGFzc3dvcmRQcm92aWRlciA9IHVzZXJJbnRlcm5hbC5wcm92aWRlckRhdGEuZmluZChcbiAgICAoeyBwcm92aWRlcklkIH0pID0+IHByb3ZpZGVySWQgPT09IFByb3ZpZGVySWQuUEFTU1dPUkRcbiAgKTtcbiAgaWYgKHBhc3N3b3JkUHJvdmlkZXIpIHtcbiAgICBwYXNzd29yZFByb3ZpZGVyLmRpc3BsYXlOYW1lID0gdXNlckludGVybmFsLmRpc3BsYXlOYW1lO1xuICAgIHBhc3N3b3JkUHJvdmlkZXIucGhvdG9VUkwgPSB1c2VySW50ZXJuYWwucGhvdG9VUkw7XG4gIH1cblxuICBhd2FpdCB1c2VySW50ZXJuYWwuX3VwZGF0ZVRva2Vuc0lmTmVjZXNzYXJ5KHJlc3BvbnNlKTtcbn1cblxuLyoqXG4gKiBVcGRhdGVzIHRoZSB1c2VyJ3MgZW1haWwgYWRkcmVzcy5cbiAqXG4gKiBAcmVtYXJrc1xuICogQW4gZW1haWwgd2lsbCBiZSBzZW50IHRvIHRoZSBvcmlnaW5hbCBlbWFpbCBhZGRyZXNzIChpZiBpdCB3YXMgc2V0KSB0aGF0IGFsbG93cyB0byByZXZva2UgdGhlXG4gKiBlbWFpbCBhZGRyZXNzIGNoYW5nZSwgaW4gb3JkZXIgdG8gcHJvdGVjdCB0aGVtIGZyb20gYWNjb3VudCBoaWphY2tpbmcuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgbm90IHN1cHBvcnRlZCBvbiBhbnkge0BsaW5rIFVzZXJ9IHNpZ25lZCBpbiBieSB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzXG4gKiBjcmVhdGVkIHdpdGggYSB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogSW1wb3J0YW50OiB0aGlzIGlzIGEgc2VjdXJpdHkgc2Vuc2l0aXZlIG9wZXJhdGlvbiB0aGF0IHJlcXVpcmVzIHRoZSB1c2VyIHRvIGhhdmUgcmVjZW50bHkgc2lnbmVkXG4gKiBpbi4gSWYgdGhpcyByZXF1aXJlbWVudCBpc24ndCBtZXQsIGFzayB0aGUgdXNlciB0byBhdXRoZW50aWNhdGUgYWdhaW4gYW5kIHRoZW4gY2FsbFxuICoge0BsaW5rIHJlYXV0aGVudGljYXRlV2l0aENyZWRlbnRpYWx9LlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKiBAcGFyYW0gbmV3RW1haWwgLSBUaGUgbmV3IGVtYWlsIGFkZHJlc3MuXG4gKlxuICogVGhyb3dzIFwiYXV0aC9vcGVyYXRpb24tbm90LWFsbG93ZWRcIiBlcnJvciB3aGVuXG4gKiB7QGxpbmsgaHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL2lkZW50aXR5LXBsYXRmb3JtL2RvY3MvYWRtaW4vZW1haWwtZW51bWVyYXRpb24tcHJvdGVjdGlvbiB8IEVtYWlsIEVudW1lcmF0aW9uIFByb3RlY3Rpb259XG4gKiBpcyBlbmFibGVkLlxuICogRGVwcmVjYXRlZCAtIFVzZSB7QGxpbmsgdmVyaWZ5QmVmb3JlVXBkYXRlRW1haWx9IGluc3RlYWQuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlRW1haWwodXNlcjogVXNlciwgbmV3RW1haWw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB1c2VySW50ZXJuYWwgPSBnZXRNb2R1bGFySW5zdGFuY2UodXNlcikgYXMgVXNlckludGVybmFsO1xuICBpZiAoX2lzRmlyZWJhc2VTZXJ2ZXJBcHAodXNlckludGVybmFsLmF1dGguYXBwKSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgIF9zZXJ2ZXJBcHBDdXJyZW50VXNlck9wZXJhdGlvbk5vdFN1cHBvcnRlZEVycm9yKHVzZXJJbnRlcm5hbC5hdXRoKVxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHVwZGF0ZUVtYWlsT3JQYXNzd29yZCh1c2VySW50ZXJuYWwsIG5ld0VtYWlsLCBudWxsKTtcbn1cblxuLyoqXG4gKiBVcGRhdGVzIHRoZSB1c2VyJ3MgcGFzc3dvcmQuXG4gKlxuICogQHJlbWFya3NcbiAqIEltcG9ydGFudDogdGhpcyBpcyBhIHNlY3VyaXR5IHNlbnNpdGl2ZSBvcGVyYXRpb24gdGhhdCByZXF1aXJlcyB0aGUgdXNlciB0byBoYXZlIHJlY2VudGx5IHNpZ25lZFxuICogaW4uIElmIHRoaXMgcmVxdWlyZW1lbnQgaXNuJ3QgbWV0LCBhc2sgdGhlIHVzZXIgdG8gYXV0aGVudGljYXRlIGFnYWluIGFuZCB0aGVuIGNhbGxcbiAqIHtAbGluayByZWF1dGhlbnRpY2F0ZVdpdGhDcmVkZW50aWFsfS5cbiAqXG4gKiBAcGFyYW0gdXNlciAtIFRoZSB1c2VyLlxuICogQHBhcmFtIG5ld1Bhc3N3b3JkIC0gVGhlIG5ldyBwYXNzd29yZC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVQYXNzd29yZCh1c2VyOiBVc2VyLCBuZXdQYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiB1cGRhdGVFbWFpbE9yUGFzc3dvcmQoXG4gICAgZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpIGFzIFVzZXJJbnRlcm5hbCxcbiAgICBudWxsLFxuICAgIG5ld1Bhc3N3b3JkXG4gICk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUVtYWlsT3JQYXNzd29yZChcbiAgdXNlcjogVXNlckludGVybmFsLFxuICBlbWFpbDogc3RyaW5nIHwgbnVsbCxcbiAgcGFzc3dvcmQ6IHN0cmluZyB8IG51bGxcbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCB7IGF1dGggfSA9IHVzZXI7XG4gIGNvbnN0IGlkVG9rZW4gPSBhd2FpdCB1c2VyLmdldElkVG9rZW4oKTtcbiAgY29uc3QgcmVxdWVzdDogVXBkYXRlRW1haWxQYXNzd29yZFJlcXVlc3QgPSB7XG4gICAgaWRUb2tlbixcbiAgICByZXR1cm5TZWN1cmVUb2tlbjogdHJ1ZVxuICB9O1xuXG4gIGlmIChlbWFpbCkge1xuICAgIHJlcXVlc3QuZW1haWwgPSBlbWFpbDtcbiAgfVxuXG4gIGlmIChwYXNzd29yZCkge1xuICAgIHJlcXVlc3QucGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgX2xvZ291dElmSW52YWxpZGF0ZWQoXG4gICAgdXNlcixcbiAgICBhcGlVcGRhdGVFbWFpbFBhc3N3b3JkKGF1dGgsIHJlcXVlc3QpXG4gICk7XG4gIGF3YWl0IHVzZXIuX3VwZGF0ZVRva2Vuc0lmTmVjZXNzYXJ5KHJlc3BvbnNlLCAvKiByZWxvYWQgKi8gdHJ1ZSk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQWRkaXRpb25hbFVzZXJJbmZvLCBVc2VyQ3JlZGVudGlhbCB9IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBJZFRva2VuUmVzcG9uc2UsIElkVG9rZW5SZXNwb25zZUtpbmQgfSBmcm9tICcuLi8uLi9tb2RlbC9pZF90b2tlbic7XG5pbXBvcnQgeyBfcGFyc2VUb2tlbiB9IGZyb20gJy4vaWRfdG9rZW5fcmVzdWx0JztcbmltcG9ydCB7IFVzZXJDcmVkZW50aWFsSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC91c2VyJztcbmltcG9ydCB7IFByb3ZpZGVySWQgfSBmcm9tICcuLi8uLi9tb2RlbC9lbnVtcyc7XG5cbi8qKlxuICogUGFyc2UgdGhlIGBBZGRpdGlvbmFsVXNlckluZm9gIGZyb20gdGhlIElEIHRva2VuIHJlc3BvbnNlLlxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9mcm9tSWRUb2tlblJlc3BvbnNlKFxuICBpZFRva2VuUmVzcG9uc2U/OiBJZFRva2VuUmVzcG9uc2Vcbik6IEFkZGl0aW9uYWxVc2VySW5mbyB8IG51bGwge1xuICBpZiAoIWlkVG9rZW5SZXNwb25zZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHsgcHJvdmlkZXJJZCB9ID0gaWRUb2tlblJlc3BvbnNlO1xuICBjb25zdCBwcm9maWxlID0gaWRUb2tlblJlc3BvbnNlLnJhd1VzZXJJbmZvXG4gICAgPyBKU09OLnBhcnNlKGlkVG9rZW5SZXNwb25zZS5yYXdVc2VySW5mbylcbiAgICA6IHt9O1xuICBjb25zdCBpc05ld1VzZXIgPVxuICAgIGlkVG9rZW5SZXNwb25zZS5pc05ld1VzZXIgfHxcbiAgICBpZFRva2VuUmVzcG9uc2Uua2luZCA9PT0gSWRUb2tlblJlc3BvbnNlS2luZC5TaWdudXBOZXdVc2VyO1xuICBpZiAoIXByb3ZpZGVySWQgJiYgaWRUb2tlblJlc3BvbnNlPy5pZFRva2VuKSB7XG4gICAgY29uc3Qgc2lnbkluUHJvdmlkZXIgPSBfcGFyc2VUb2tlbihpZFRva2VuUmVzcG9uc2UuaWRUb2tlbik/LmZpcmViYXNlPy5bXG4gICAgICAnc2lnbl9pbl9wcm92aWRlcidcbiAgICBdO1xuICAgIGlmIChzaWduSW5Qcm92aWRlcikge1xuICAgICAgY29uc3QgZmlsdGVyZWRQcm92aWRlcklkID1cbiAgICAgICAgc2lnbkluUHJvdmlkZXIgIT09IFByb3ZpZGVySWQuQU5PTllNT1VTICYmXG4gICAgICAgIHNpZ25JblByb3ZpZGVyICE9PSBQcm92aWRlcklkLkNVU1RPTVxuICAgICAgICAgID8gKHNpZ25JblByb3ZpZGVyIGFzIFByb3ZpZGVySWQpXG4gICAgICAgICAgOiBudWxsO1xuICAgICAgLy8gVXNlcyBnZW5lcmljIGNsYXNzIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgbGVnYWN5IFNESy5cbiAgICAgIHJldHVybiBuZXcgR2VuZXJpY0FkZGl0aW9uYWxVc2VySW5mbyhpc05ld1VzZXIsIGZpbHRlcmVkUHJvdmlkZXJJZCk7XG4gICAgfVxuICB9XG4gIGlmICghcHJvdmlkZXJJZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHN3aXRjaCAocHJvdmlkZXJJZCkge1xuICAgIGNhc2UgUHJvdmlkZXJJZC5GQUNFQk9PSzpcbiAgICAgIHJldHVybiBuZXcgRmFjZWJvb2tBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm9maWxlKTtcbiAgICBjYXNlIFByb3ZpZGVySWQuR0lUSFVCOlxuICAgICAgcmV0dXJuIG5ldyBHaXRodWJBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm9maWxlKTtcbiAgICBjYXNlIFByb3ZpZGVySWQuR09PR0xFOlxuICAgICAgcmV0dXJuIG5ldyBHb29nbGVBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm9maWxlKTtcbiAgICBjYXNlIFByb3ZpZGVySWQuVFdJVFRFUjpcbiAgICAgIHJldHVybiBuZXcgVHdpdHRlckFkZGl0aW9uYWxVc2VySW5mbyhcbiAgICAgICAgaXNOZXdVc2VyLFxuICAgICAgICBwcm9maWxlLFxuICAgICAgICBpZFRva2VuUmVzcG9uc2Uuc2NyZWVuTmFtZSB8fCBudWxsXG4gICAgICApO1xuICAgIGNhc2UgUHJvdmlkZXJJZC5DVVNUT006XG4gICAgY2FzZSBQcm92aWRlcklkLkFOT05ZTU9VUzpcbiAgICAgIHJldHVybiBuZXcgR2VuZXJpY0FkZGl0aW9uYWxVc2VySW5mbyhpc05ld1VzZXIsIG51bGwpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbmV3IEdlbmVyaWNBZGRpdGlvbmFsVXNlckluZm8oaXNOZXdVc2VyLCBwcm92aWRlcklkLCBwcm9maWxlKTtcbiAgfVxufVxuXG5jbGFzcyBHZW5lcmljQWRkaXRpb25hbFVzZXJJbmZvIGltcGxlbWVudHMgQWRkaXRpb25hbFVzZXJJbmZvIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcmVhZG9ubHkgaXNOZXdVc2VyOiBib29sZWFuLFxuICAgIHJlYWRvbmx5IHByb3ZpZGVySWQ6IFByb3ZpZGVySWQgfCBzdHJpbmcgfCBudWxsLFxuICAgIHJlYWRvbmx5IHByb2ZpbGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge31cbiAgKSB7fVxufVxuXG5jbGFzcyBGZWRlcmF0ZWRBZGRpdGlvbmFsVXNlckluZm9XaXRoVXNlcm5hbWUgZXh0ZW5kcyBHZW5lcmljQWRkaXRpb25hbFVzZXJJbmZvIHtcbiAgY29uc3RydWN0b3IoXG4gICAgaXNOZXdVc2VyOiBib29sZWFuLFxuICAgIHByb3ZpZGVySWQ6IFByb3ZpZGVySWQsXG4gICAgcHJvZmlsZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgcmVhZG9ubHkgdXNlcm5hbWU6IHN0cmluZyB8IG51bGxcbiAgKSB7XG4gICAgc3VwZXIoaXNOZXdVc2VyLCBwcm92aWRlcklkLCBwcm9maWxlKTtcbiAgfVxufVxuXG5jbGFzcyBGYWNlYm9va0FkZGl0aW9uYWxVc2VySW5mbyBleHRlbmRzIEdlbmVyaWNBZGRpdGlvbmFsVXNlckluZm8ge1xuICBjb25zdHJ1Y3Rvcihpc05ld1VzZXI6IGJvb2xlYW4sIHByb2ZpbGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgc3VwZXIoaXNOZXdVc2VyLCBQcm92aWRlcklkLkZBQ0VCT09LLCBwcm9maWxlKTtcbiAgfVxufVxuXG5jbGFzcyBHaXRodWJBZGRpdGlvbmFsVXNlckluZm8gZXh0ZW5kcyBGZWRlcmF0ZWRBZGRpdGlvbmFsVXNlckluZm9XaXRoVXNlcm5hbWUge1xuICBjb25zdHJ1Y3Rvcihpc05ld1VzZXI6IGJvb2xlYW4sIHByb2ZpbGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgc3VwZXIoXG4gICAgICBpc05ld1VzZXIsXG4gICAgICBQcm92aWRlcklkLkdJVEhVQixcbiAgICAgIHByb2ZpbGUsXG4gICAgICB0eXBlb2YgcHJvZmlsZT8ubG9naW4gPT09ICdzdHJpbmcnID8gcHJvZmlsZT8ubG9naW4gOiBudWxsXG4gICAgKTtcbiAgfVxufVxuXG5jbGFzcyBHb29nbGVBZGRpdGlvbmFsVXNlckluZm8gZXh0ZW5kcyBHZW5lcmljQWRkaXRpb25hbFVzZXJJbmZvIHtcbiAgY29uc3RydWN0b3IoaXNOZXdVc2VyOiBib29sZWFuLCBwcm9maWxlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIHN1cGVyKGlzTmV3VXNlciwgUHJvdmlkZXJJZC5HT09HTEUsIHByb2ZpbGUpO1xuICB9XG59XG5cbmNsYXNzIFR3aXR0ZXJBZGRpdGlvbmFsVXNlckluZm8gZXh0ZW5kcyBGZWRlcmF0ZWRBZGRpdGlvbmFsVXNlckluZm9XaXRoVXNlcm5hbWUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBpc05ld1VzZXI6IGJvb2xlYW4sXG4gICAgcHJvZmlsZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgc2NyZWVuTmFtZTogc3RyaW5nIHwgbnVsbFxuICApIHtcbiAgICBzdXBlcihpc05ld1VzZXIsIFByb3ZpZGVySWQuVFdJVFRFUiwgcHJvZmlsZSwgc2NyZWVuTmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBFeHRyYWN0cyBwcm92aWRlciBzcGVjaWZpYyB7QGxpbmsgQWRkaXRpb25hbFVzZXJJbmZvfSBmb3IgdGhlIGdpdmVuIGNyZWRlbnRpYWwuXG4gKlxuICogQHBhcmFtIHVzZXJDcmVkZW50aWFsIC0gVGhlIHVzZXIgY3JlZGVudGlhbC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRpdGlvbmFsVXNlckluZm8oXG4gIHVzZXJDcmVkZW50aWFsOiBVc2VyQ3JlZGVudGlhbFxuKTogQWRkaXRpb25hbFVzZXJJbmZvIHwgbnVsbCB7XG4gIGNvbnN0IHsgdXNlciwgX3Rva2VuUmVzcG9uc2UgfSA9IHVzZXJDcmVkZW50aWFsIGFzIFVzZXJDcmVkZW50aWFsSW50ZXJuYWw7XG4gIGlmICh1c2VyLmlzQW5vbnltb3VzICYmICFfdG9rZW5SZXNwb25zZSkge1xuICAgIC8vIEhhbmRsZSB0aGUgc3BlY2lhbCBjYXNlIHdoZXJlIHNpZ25JbkFub255bW91c2x5KCkgZ2V0cyBjYWxsZWQgdHdpY2UuXG4gICAgLy8gTm8gbmV0d29yayBjYWxsIGlzIG1hZGUgc28gdGhlcmUncyBub3RoaW5nIHRvIGFjdHVhbGx5IGZpbGwgdGhpcyBpblxuICAgIHJldHVybiB7XG4gICAgICBwcm92aWRlcklkOiBudWxsLFxuICAgICAgaXNOZXdVc2VyOiBmYWxzZSxcbiAgICAgIHByb2ZpbGU6IG51bGxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIF9mcm9tSWRUb2tlblJlc3BvbnNlKF90b2tlblJlc3BvbnNlKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQge1xuICBBdXRoLFxuICBOZXh0T3JPYnNlcnZlcixcbiAgUGVyc2lzdGVuY2UsXG4gIFVzZXIsXG4gIENvbXBsZXRlRm4sXG4gIEVycm9yRm4sXG4gIFVuc3Vic2NyaWJlLFxuICBQYXNzd29yZFZhbGlkYXRpb25TdGF0dXNcbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IF9pbml0aWFsaXplUmVjYXB0Y2hhQ29uZmlnIH0gZnJvbSAnLi4vcGxhdGZvcm1fYnJvd3Nlci9yZWNhcHRjaGEvcmVjYXB0Y2hhX2VudGVycHJpc2VfdmVyaWZpZXInO1xuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5cbmV4cG9ydCB7XG4gIGRlYnVnRXJyb3JNYXAsXG4gIHByb2RFcnJvck1hcCxcbiAgQVVUSF9FUlJPUl9DT0RFU19NQVBfRE9fTk9UX1VTRV9JTlRFUk5BTExZIGFzIEF1dGhFcnJvckNvZGVzXG59IGZyb20gJy4vZXJyb3JzJztcblxuLy8gTm9uLW9wdGlvbmFsIGF1dGggbWV0aG9kcy5cbi8qKlxuICogQ2hhbmdlcyB0aGUgdHlwZSBvZiBwZXJzaXN0ZW5jZSBvbiB0aGUge0BsaW5rIEF1dGh9IGluc3RhbmNlIGZvciB0aGUgY3VycmVudGx5IHNhdmVkXG4gKiBgQXV0aGAgc2Vzc2lvbiBhbmQgYXBwbGllcyB0aGlzIHR5cGUgb2YgcGVyc2lzdGVuY2UgZm9yIGZ1dHVyZSBzaWduLWluIHJlcXVlc3RzLCBpbmNsdWRpbmdcbiAqIHNpZ24taW4gd2l0aCByZWRpcmVjdCByZXF1ZXN0cy5cbiAqXG4gKiBAcmVtYXJrc1xuICogVGhpcyBtYWtlcyBpdCBlYXN5IGZvciBhIHVzZXIgc2lnbmluZyBpbiB0byBzcGVjaWZ5IHdoZXRoZXIgdGhlaXIgc2Vzc2lvbiBzaG91bGQgYmVcbiAqIHJlbWVtYmVyZWQgb3Igbm90LiBJdCBhbHNvIG1ha2VzIGl0IGVhc2llciB0byBuZXZlciBwZXJzaXN0IHRoZSBgQXV0aGAgc3RhdGUgZm9yIGFwcGxpY2F0aW9uc1xuICogdGhhdCBhcmUgc2hhcmVkIGJ5IG90aGVyIHVzZXJzIG9yIGhhdmUgc2Vuc2l0aXZlIGRhdGEuXG4gKlxuICogVGhpcyBtZXRob2QgZG9lcyBub3Qgd29yayBpbiBhIE5vZGUuanMgZW52aXJvbm1lbnQgb3Igd2l0aCB7QGxpbmsgQXV0aH0gaW5zdGFuY2VzIGNyZWF0ZWQgd2l0aCBhXG4gKiB7QGxpbmsgQGZpcmViYXNlL2FwcCNGaXJlYmFzZVNlcnZlckFwcH0uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHNldFBlcnNpc3RlbmNlKGF1dGgsIGJyb3dzZXJTZXNzaW9uUGVyc2lzdGVuY2UpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIHBlcnNpc3RlbmNlIC0gVGhlIHtAbGluayBQZXJzaXN0ZW5jZX0gdG8gdXNlLlxuICogQHJldHVybnMgQSBgUHJvbWlzZWAgdGhhdCByZXNvbHZlcyBvbmNlIHRoZSBwZXJzaXN0ZW5jZSBjaGFuZ2UgaGFzIGNvbXBsZXRlZFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFBlcnNpc3RlbmNlKFxuICBhdXRoOiBBdXRoLFxuICBwZXJzaXN0ZW5jZTogUGVyc2lzdGVuY2Vcbik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpLnNldFBlcnNpc3RlbmNlKHBlcnNpc3RlbmNlKTtcbn1cblxuLyoqXG4gKiBMb2FkcyB0aGUgcmVDQVBUQ0hBIGNvbmZpZ3VyYXRpb24gaW50byB0aGUgYEF1dGhgIGluc3RhbmNlLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIHdpbGwgbG9hZCB0aGUgcmVDQVBUQ0hBIGNvbmZpZywgd2hpY2ggaW5kaWNhdGVzIHdoZXRoZXIgdGhlIHJlQ0FQVENIQVxuICogdmVyaWZpY2F0aW9uIGZsb3cgc2hvdWxkIGJlIHRyaWdnZXJlZCBmb3IgZWFjaCBhdXRoIHByb3ZpZGVyLCBpbnRvIHRoZVxuICogY3VycmVudCBBdXRoIHNlc3Npb24uXG4gKlxuICogSWYgaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZygpIGlzIG5vdCBpbnZva2VkLCB0aGUgYXV0aCBmbG93IHdpbGwgYWx3YXlzIHN0YXJ0XG4gKiB3aXRob3V0IHJlQ0FQVENIQSB2ZXJpZmljYXRpb24uIElmIHRoZSBwcm92aWRlciBpcyBjb25maWd1cmVkIHRvIHJlcXVpcmUgcmVDQVBUQ0hBXG4gKiB2ZXJpZmljYXRpb24sIHRoZSBTREsgd2lsbCB0cmFuc3BhcmVudGx5IGxvYWQgdGhlIHJlQ0FQVENIQSBjb25maWcgYW5kIHJlc3RhcnQgdGhlXG4gKiBhdXRoIGZsb3dzLlxuICpcbiAqIFRodXMsIGJ5IGNhbGxpbmcgdGhpcyBvcHRpb25hbCBtZXRob2QsIHlvdSB3aWxsIHJlZHVjZSB0aGUgbGF0ZW5jeSBvZiBmdXR1cmUgYXV0aCBmbG93cy5cbiAqIExvYWRpbmcgdGhlIHJlQ0FQVENIQSBjb25maWcgZWFybHkgd2lsbCBhbHNvIGVuaGFuY2UgdGhlIHNpZ25hbCBjb2xsZWN0ZWQgYnkgcmVDQVBUQ0hBLlxuICpcbiAqIFRoaXMgbWV0aG9kIGRvZXMgbm90IHdvcmsgaW4gYSBOb2RlLmpzIGVudmlyb25tZW50LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBpbml0aWFsaXplUmVjYXB0Y2hhQ29uZmlnKGF1dGgpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVSZWNhcHRjaGFDb25maWcoYXV0aDogQXV0aCk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gX2luaXRpYWxpemVSZWNhcHRjaGFDb25maWcoYXV0aCk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHRoZSBwYXNzd29yZCBhZ2FpbnN0IHRoZSBwYXNzd29yZCBwb2xpY3kgY29uZmlndXJlZCBmb3IgdGhlIHByb2plY3Qgb3IgdGVuYW50LlxuICpcbiAqIEByZW1hcmtzXG4gKiBJZiBubyB0ZW5hbnQgSUQgaXMgc2V0IG9uIHRoZSBgQXV0aGAgaW5zdGFuY2UsIHRoZW4gdGhpcyBtZXRob2Qgd2lsbCB1c2UgdGhlIHBhc3N3b3JkXG4gKiBwb2xpY3kgY29uZmlndXJlZCBmb3IgdGhlIHByb2plY3QuIE90aGVyd2lzZSwgdGhpcyBtZXRob2Qgd2lsbCB1c2UgdGhlIHBvbGljeSBjb25maWd1cmVkXG4gKiBmb3IgdGhlIHRlbmFudC4gSWYgYSBwYXNzd29yZCBwb2xpY3kgaGFzIG5vdCBiZWVuIGNvbmZpZ3VyZWQsIHRoZW4gdGhlIGRlZmF1bHQgcG9saWN5XG4gKiBjb25maWd1cmVkIGZvciBhbGwgcHJvamVjdHMgd2lsbCBiZSB1c2VkLlxuICpcbiAqIElmIGFuIGF1dGggZmxvdyBmYWlscyBiZWNhdXNlIGEgc3VibWl0dGVkIHBhc3N3b3JkIGRvZXMgbm90IG1lZXQgdGhlIHBhc3N3b3JkIHBvbGljeVxuICogcmVxdWlyZW1lbnRzIGFuZCB0aGlzIG1ldGhvZCBoYXMgcHJldmlvdXNseSBiZWVuIGNhbGxlZCwgdGhlbiB0aGlzIG1ldGhvZCB3aWxsIHVzZSB0aGVcbiAqIG1vc3QgcmVjZW50IHBvbGljeSBhdmFpbGFibGUgd2hlbiBjYWxsZWQgYWdhaW4uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHZhbGlkYXRlUGFzc3dvcmQoYXV0aCwgJ3NvbWUtcGFzc3dvcmQnKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBhdXRoIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gcGFzc3dvcmQgVGhlIHBhc3N3b3JkIHRvIHZhbGlkYXRlLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlUGFzc3dvcmQoXG4gIGF1dGg6IEF1dGgsXG4gIHBhc3N3b3JkOiBzdHJpbmdcbik6IFByb21pc2U8UGFzc3dvcmRWYWxpZGF0aW9uU3RhdHVzPiB7XG4gIGNvbnN0IGF1dGhJbnRlcm5hbCA9IF9jYXN0QXV0aChhdXRoKTtcbiAgcmV0dXJuIGF1dGhJbnRlcm5hbC52YWxpZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKTtcbn1cblxuLyoqXG4gKiBBZGRzIGFuIG9ic2VydmVyIGZvciBjaGFuZ2VzIHRvIHRoZSBzaWduZWQtaW4gdXNlcidzIElEIHRva2VuLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGluY2x1ZGVzIHNpZ24taW4sIHNpZ24tb3V0LCBhbmQgdG9rZW4gcmVmcmVzaCBldmVudHMuXG4gKiBUaGlzIHdpbGwgbm90IGJlIHRyaWdnZXJlZCBhdXRvbWF0aWNhbGx5IHVwb24gSUQgdG9rZW4gZXhwaXJhdGlvbi4gVXNlIHtAbGluayBVc2VyLmdldElkVG9rZW59IHRvIHJlZnJlc2ggdGhlIElEIHRva2VuLlxuICpcbiAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqIEBwYXJhbSBuZXh0T3JPYnNlcnZlciAtIGNhbGxiYWNrIHRyaWdnZXJlZCBvbiBjaGFuZ2UuXG4gKiBAcGFyYW0gZXJyb3IgLSBEZXByZWNhdGVkLiBUaGlzIGNhbGxiYWNrIGlzIG5ldmVyIHRyaWdnZXJlZC4gRXJyb3JzXG4gKiBvbiBzaWduaW5nIGluL291dCBjYW4gYmUgY2F1Z2h0IGluIHByb21pc2VzIHJldHVybmVkIGZyb21cbiAqIHNpZ24taW4vc2lnbi1vdXQgZnVuY3Rpb25zLlxuICogQHBhcmFtIGNvbXBsZXRlZCAtIERlcHJlY2F0ZWQuIFRoaXMgY2FsbGJhY2sgaXMgbmV2ZXIgdHJpZ2dlcmVkLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uSWRUb2tlbkNoYW5nZWQoXG4gIGF1dGg6IEF1dGgsXG4gIG5leHRPck9ic2VydmVyOiBOZXh0T3JPYnNlcnZlcjxVc2VyPixcbiAgZXJyb3I/OiBFcnJvckZuLFxuICBjb21wbGV0ZWQ/OiBDb21wbGV0ZUZuXG4pOiBVbnN1YnNjcmliZSB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkub25JZFRva2VuQ2hhbmdlZChcbiAgICBuZXh0T3JPYnNlcnZlcixcbiAgICBlcnJvcixcbiAgICBjb21wbGV0ZWRcbiAgKTtcbn1cbi8qKlxuICogQWRkcyBhIGJsb2NraW5nIGNhbGxiYWNrIHRoYXQgcnVucyBiZWZvcmUgYW4gYXV0aCBzdGF0ZSBjaGFuZ2VcbiAqIHNldHMgYSBuZXcgdXNlci5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gY2FsbGJhY2sgLSBjYWxsYmFjayB0cmlnZ2VyZWQgYmVmb3JlIG5ldyB1c2VyIHZhbHVlIGlzIHNldC5cbiAqICAgSWYgdGhpcyB0aHJvd3MsIGl0IGJsb2NrcyB0aGUgdXNlciBmcm9tIGJlaW5nIHNldC5cbiAqIEBwYXJhbSBvbkFib3J0IC0gY2FsbGJhY2sgdHJpZ2dlcmVkIGlmIGEgbGF0ZXIgYGJlZm9yZUF1dGhTdGF0ZUNoYW5nZWQoKWBcbiAqICAgY2FsbGJhY2sgdGhyb3dzLCBhbGxvd2luZyB5b3UgdG8gdW5kbyBhbnkgc2lkZSBlZmZlY3RzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmVmb3JlQXV0aFN0YXRlQ2hhbmdlZChcbiAgYXV0aDogQXV0aCxcbiAgY2FsbGJhY2s6ICh1c2VyOiBVc2VyIHwgbnVsbCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4sXG4gIG9uQWJvcnQ/OiAoKSA9PiB2b2lkXG4pOiBVbnN1YnNjcmliZSB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkuYmVmb3JlQXV0aFN0YXRlQ2hhbmdlZChjYWxsYmFjaywgb25BYm9ydCk7XG59XG4vKipcbiAqIEFkZHMgYW4gb2JzZXJ2ZXIgZm9yIGNoYW5nZXMgdG8gdGhlIHVzZXIncyBzaWduLWluIHN0YXRlLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUbyBrZWVwIHRoZSBvbGQgYmVoYXZpb3IsIHNlZSB7QGxpbmsgb25JZFRva2VuQ2hhbmdlZH0uXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIG5leHRPck9ic2VydmVyIC0gY2FsbGJhY2sgdHJpZ2dlcmVkIG9uIGNoYW5nZS5cbiAqIEBwYXJhbSBlcnJvciAtIERlcHJlY2F0ZWQuIFRoaXMgY2FsbGJhY2sgaXMgbmV2ZXIgdHJpZ2dlcmVkLiBFcnJvcnNcbiAqIG9uIHNpZ25pbmcgaW4vb3V0IGNhbiBiZSBjYXVnaHQgaW4gcHJvbWlzZXMgcmV0dXJuZWQgZnJvbVxuICogc2lnbi1pbi9zaWduLW91dCBmdW5jdGlvbnMuXG4gKiBAcGFyYW0gY29tcGxldGVkIC0gRGVwcmVjYXRlZC4gVGhpcyBjYWxsYmFjayBpcyBuZXZlciB0cmlnZ2VyZWQuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25BdXRoU3RhdGVDaGFuZ2VkKFxuICBhdXRoOiBBdXRoLFxuICBuZXh0T3JPYnNlcnZlcjogTmV4dE9yT2JzZXJ2ZXI8VXNlcj4sXG4gIGVycm9yPzogRXJyb3JGbixcbiAgY29tcGxldGVkPzogQ29tcGxldGVGblxuKTogVW5zdWJzY3JpYmUge1xuICByZXR1cm4gZ2V0TW9kdWxhckluc3RhbmNlKGF1dGgpLm9uQXV0aFN0YXRlQ2hhbmdlZChcbiAgICBuZXh0T3JPYnNlcnZlcixcbiAgICBlcnJvcixcbiAgICBjb21wbGV0ZWRcbiAgKTtcbn1cbi8qKlxuICogU2V0cyB0aGUgY3VycmVudCBsYW5ndWFnZSB0byB0aGUgZGVmYXVsdCBkZXZpY2UvYnJvd3NlciBwcmVmZXJlbmNlLlxuICpcbiAqIEBwYXJhbSBhdXRoIC0gVGhlIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VEZXZpY2VMYW5ndWFnZShhdXRoOiBBdXRoKTogdm9pZCB7XG4gIGdldE1vZHVsYXJJbnN0YW5jZShhdXRoKS51c2VEZXZpY2VMYW5ndWFnZSgpO1xufVxuLyoqXG4gKiBBc3luY2hyb25vdXNseSBzZXRzIHRoZSBwcm92aWRlZCB1c2VyIGFzIHtAbGluayBBdXRoLmN1cnJlbnRVc2VyfSBvbiB0aGVcbiAqIHtAbGluayBBdXRofSBpbnN0YW5jZS5cbiAqXG4gKiBAcmVtYXJrc1xuICogQSBuZXcgaW5zdGFuY2UgY29weSBvZiB0aGUgdXNlciBwcm92aWRlZCB3aWxsIGJlIG1hZGUgYW5kIHNldCBhcyBjdXJyZW50VXNlci5cbiAqXG4gKiBUaGlzIHdpbGwgdHJpZ2dlciB7QGxpbmsgb25BdXRoU3RhdGVDaGFuZ2VkfSBhbmQge0BsaW5rIG9uSWRUb2tlbkNoYW5nZWR9IGxpc3RlbmVyc1xuICogbGlrZSBvdGhlciBzaWduIGluIG1ldGhvZHMuXG4gKlxuICogVGhlIG9wZXJhdGlvbiBmYWlscyB3aXRoIGFuIGVycm9yIGlmIHRoZSB1c2VyIHRvIGJlIHVwZGF0ZWQgYmVsb25ncyB0byBhIGRpZmZlcmVudCBGaXJlYmFzZVxuICogcHJvamVjdC5cbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gdXNlciAtIFRoZSBuZXcge0BsaW5rIFVzZXJ9LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUN1cnJlbnRVc2VyKFxuICBhdXRoOiBBdXRoLFxuICB1c2VyOiBVc2VyIHwgbnVsbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkudXBkYXRlQ3VycmVudFVzZXIodXNlcik7XG59XG4vKipcbiAqIFNpZ25zIG91dCB0aGUgY3VycmVudCB1c2VyLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIG1ldGhvZCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHtAbGluayBBdXRofSBpbnN0YW5jZXMgY3JlYXRlZCB3aXRoIGFcbiAqIHtAbGluayBAZmlyZWJhc2UvYXBwI0ZpcmViYXNlU2VydmVyQXBwfS5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2lnbk91dChhdXRoOiBBdXRoKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCkuc2lnbk91dCgpO1xufVxuXG4vKipcbiAqIFJldm9rZXMgdGhlIGdpdmVuIGFjY2VzcyB0b2tlbi4gQ3VycmVudGx5IG9ubHkgc3VwcG9ydHMgQXBwbGUgT0F1dGggYWNjZXNzIHRva2Vucy5cbiAqXG4gKiBAcGFyYW0gYXV0aCAtIFRoZSB7QGxpbmsgQXV0aH0gaW5zdGFuY2UuXG4gKiBAcGFyYW0gdG9rZW4gLSBUaGUgQXBwbGUgT0F1dGggYWNjZXNzIHRva2VuLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldm9rZUFjY2Vzc1Rva2VuKGF1dGg6IEF1dGgsIHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgYXV0aEludGVybmFsID0gX2Nhc3RBdXRoKGF1dGgpO1xuICByZXR1cm4gYXV0aEludGVybmFsLnJldm9rZUFjY2Vzc1Rva2VuKHRva2VuKTtcbn1cblxuZXhwb3J0IHsgaW5pdGlhbGl6ZUF1dGggfSBmcm9tICcuL2F1dGgvaW5pdGlhbGl6ZSc7XG5leHBvcnQgeyBjb25uZWN0QXV0aEVtdWxhdG9yIH0gZnJvbSAnLi9hdXRoL2VtdWxhdG9yJztcblxuLy8gY3JlZGVudGlhbHNcbmV4cG9ydCB7IEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi9jcmVkZW50aWFscyc7XG5leHBvcnQgeyBFbWFpbEF1dGhDcmVkZW50aWFsIH0gZnJvbSAnLi9jcmVkZW50aWFscy9lbWFpbCc7XG5leHBvcnQgeyBPQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2NyZWRlbnRpYWxzL29hdXRoJztcbmV4cG9ydCB7IFBob25lQXV0aENyZWRlbnRpYWwgfSBmcm9tICcuL2NyZWRlbnRpYWxzL3Bob25lJztcblxuLy8gcGVyc2lzdGVuY2VcbmV4cG9ydCB7IGluTWVtb3J5UGVyc2lzdGVuY2UgfSBmcm9tICcuL3BlcnNpc3RlbmNlL2luX21lbW9yeSc7XG5cbi8vIHByb3ZpZGVyc1xuZXhwb3J0IHsgRW1haWxBdXRoUHJvdmlkZXIgfSBmcm9tICcuL3Byb3ZpZGVycy9lbWFpbCc7XG5leHBvcnQgeyBGYWNlYm9va0F1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL2ZhY2Vib29rJztcbmV4cG9ydCB7IEN1c3RvbVBhcmFtZXRlcnMgfSBmcm9tICcuL3Byb3ZpZGVycy9mZWRlcmF0ZWQnO1xuZXhwb3J0IHsgR29vZ2xlQXV0aFByb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlcnMvZ29vZ2xlJztcbmV4cG9ydCB7IEdpdGh1YkF1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL2dpdGh1Yic7XG5leHBvcnQgeyBPQXV0aFByb3ZpZGVyLCBPQXV0aENyZWRlbnRpYWxPcHRpb25zIH0gZnJvbSAnLi9wcm92aWRlcnMvb2F1dGgnO1xuZXhwb3J0IHsgU0FNTEF1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL3NhbWwnO1xuZXhwb3J0IHsgVHdpdHRlckF1dGhQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL3R3aXR0ZXInO1xuXG4vLyBzdHJhdGVnaWVzXG5leHBvcnQgeyBzaWduSW5Bbm9ueW1vdXNseSB9IGZyb20gJy4vc3RyYXRlZ2llcy9hbm9ueW1vdXMnO1xuZXhwb3J0IHtcbiAgc2lnbkluV2l0aENyZWRlbnRpYWwsXG4gIGxpbmtXaXRoQ3JlZGVudGlhbCxcbiAgcmVhdXRoZW50aWNhdGVXaXRoQ3JlZGVudGlhbFxufSBmcm9tICcuL3N0cmF0ZWdpZXMvY3JlZGVudGlhbCc7XG5leHBvcnQgeyBzaWduSW5XaXRoQ3VzdG9tVG9rZW4gfSBmcm9tICcuL3N0cmF0ZWdpZXMvY3VzdG9tX3Rva2VuJztcbmV4cG9ydCB7XG4gIHNlbmRQYXNzd29yZFJlc2V0RW1haWwsXG4gIGNvbmZpcm1QYXNzd29yZFJlc2V0LFxuICBhcHBseUFjdGlvbkNvZGUsXG4gIGNoZWNrQWN0aW9uQ29kZSxcbiAgdmVyaWZ5UGFzc3dvcmRSZXNldENvZGUsXG4gIGNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZCxcbiAgc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmRcbn0gZnJvbSAnLi9zdHJhdGVnaWVzL2VtYWlsX2FuZF9wYXNzd29yZCc7XG5leHBvcnQge1xuICBzZW5kU2lnbkluTGlua1RvRW1haWwsXG4gIGlzU2lnbkluV2l0aEVtYWlsTGluayxcbiAgc2lnbkluV2l0aEVtYWlsTGlua1xufSBmcm9tICcuL3N0cmF0ZWdpZXMvZW1haWxfbGluayc7XG5leHBvcnQge1xuICBmZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbCxcbiAgc2VuZEVtYWlsVmVyaWZpY2F0aW9uLFxuICB2ZXJpZnlCZWZvcmVVcGRhdGVFbWFpbFxufSBmcm9tICcuL3N0cmF0ZWdpZXMvZW1haWwnO1xuXG4vLyBjb3JlXG5leHBvcnQgeyBBY3Rpb25Db2RlVVJMLCBwYXJzZUFjdGlvbkNvZGVVUkwgfSBmcm9tICcuL2FjdGlvbl9jb2RlX3VybCc7XG5cbi8vIHVzZXJcbmV4cG9ydCB7XG4gIHVwZGF0ZVByb2ZpbGUsXG4gIHVwZGF0ZUVtYWlsLFxuICB1cGRhdGVQYXNzd29yZFxufSBmcm9tICcuL3VzZXIvYWNjb3VudF9pbmZvJztcbmV4cG9ydCB7IGdldElkVG9rZW4sIGdldElkVG9rZW5SZXN1bHQgfSBmcm9tICcuL3VzZXIvaWRfdG9rZW5fcmVzdWx0JztcbmV4cG9ydCB7IHVubGluayB9IGZyb20gJy4vdXNlci9saW5rX3VubGluayc7XG5leHBvcnQgeyBnZXRBZGRpdGlvbmFsVXNlckluZm8gfSBmcm9tICcuL3VzZXIvYWRkaXRpb25hbF91c2VyX2luZm8nO1xuXG4vLyBOb24tb3B0aW9uYWwgdXNlciBtZXRob2RzLlxuZXhwb3J0IHsgcmVsb2FkIH0gZnJvbSAnLi91c2VyL3JlbG9hZCc7XG4vKipcbiAqIERlbGV0ZXMgYW5kIHNpZ25zIG91dCB0aGUgdXNlci5cbiAqXG4gKiBAcmVtYXJrc1xuICogSW1wb3J0YW50OiB0aGlzIGlzIGEgc2VjdXJpdHktc2Vuc2l0aXZlIG9wZXJhdGlvbiB0aGF0IHJlcXVpcmVzIHRoZSB1c2VyIHRvIGhhdmUgcmVjZW50bHlcbiAqIHNpZ25lZCBpbi4gSWYgdGhpcyByZXF1aXJlbWVudCBpc24ndCBtZXQsIGFzayB0aGUgdXNlciB0byBhdXRoZW50aWNhdGUgYWdhaW4gYW5kIHRoZW4gY2FsbFxuICoge0BsaW5rIHJlYXV0aGVudGljYXRlV2l0aENyZWRlbnRpYWx9LlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlVXNlcih1c2VyOiBVc2VyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBnZXRNb2R1bGFySW5zdGFuY2UodXNlcikuZGVsZXRlKCk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvclNlc3Npb24gfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgZW51bSBNdWx0aUZhY3RvclNlc3Npb25UeXBlIHtcbiAgRU5ST0xMID0gJ2Vucm9sbCcsXG4gIFNJR05fSU4gPSAnc2lnbmluJ1xufVxuXG5pbnRlcmZhY2UgU2VyaWFsaXplZE11bHRpRmFjdG9yU2Vzc2lvbiB7XG4gIG11bHRpRmFjdG9yU2Vzc2lvbjoge1xuICAgIGlkVG9rZW4/OiBzdHJpbmc7XG4gICAgcGVuZGluZ0NyZWRlbnRpYWw/OiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBjbGFzcyBNdWx0aUZhY3RvclNlc3Npb25JbXBsIGltcGxlbWVudHMgTXVsdGlGYWN0b3JTZXNzaW9uIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSB0eXBlOiBNdWx0aUZhY3RvclNlc3Npb25UeXBlLFxuICAgIHJlYWRvbmx5IGNyZWRlbnRpYWw6IHN0cmluZyxcbiAgICByZWFkb25seSB1c2VyPzogVXNlckludGVybmFsXG4gICkge31cblxuICBzdGF0aWMgX2Zyb21JZHRva2VuKFxuICAgIGlkVG9rZW46IHN0cmluZyxcbiAgICB1c2VyPzogVXNlckludGVybmFsXG4gICk6IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwge1xuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JTZXNzaW9uSW1wbChcbiAgICAgIE11bHRpRmFjdG9yU2Vzc2lvblR5cGUuRU5ST0xMLFxuICAgICAgaWRUb2tlbixcbiAgICAgIHVzZXJcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIF9mcm9tTWZhUGVuZGluZ0NyZWRlbnRpYWwoXG4gICAgbWZhUGVuZGluZ0NyZWRlbnRpYWw6IHN0cmluZ1xuICApOiBNdWx0aUZhY3RvclNlc3Npb25JbXBsIHtcbiAgICByZXR1cm4gbmV3IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwoXG4gICAgICBNdWx0aUZhY3RvclNlc3Npb25UeXBlLlNJR05fSU4sXG4gICAgICBtZmFQZW5kaW5nQ3JlZGVudGlhbFxuICAgICk7XG4gIH1cblxuICB0b0pTT04oKTogU2VyaWFsaXplZE11bHRpRmFjdG9yU2Vzc2lvbiB7XG4gICAgY29uc3Qga2V5ID1cbiAgICAgIHRoaXMudHlwZSA9PT0gTXVsdGlGYWN0b3JTZXNzaW9uVHlwZS5FTlJPTExcbiAgICAgICAgPyAnaWRUb2tlbidcbiAgICAgICAgOiAncGVuZGluZ0NyZWRlbnRpYWwnO1xuICAgIHJldHVybiB7XG4gICAgICBtdWx0aUZhY3RvclNlc3Npb246IHtcbiAgICAgICAgW2tleV06IHRoaXMuY3JlZGVudGlhbFxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgZnJvbUpTT04oXG4gICAgb2JqOiBQYXJ0aWFsPFNlcmlhbGl6ZWRNdWx0aUZhY3RvclNlc3Npb24+XG4gICk6IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwgfCBudWxsIHtcbiAgICBpZiAob2JqPy5tdWx0aUZhY3RvclNlc3Npb24pIHtcbiAgICAgIGlmIChvYmoubXVsdGlGYWN0b3JTZXNzaW9uPy5wZW5kaW5nQ3JlZGVudGlhbCkge1xuICAgICAgICByZXR1cm4gTXVsdGlGYWN0b3JTZXNzaW9uSW1wbC5fZnJvbU1mYVBlbmRpbmdDcmVkZW50aWFsKFxuICAgICAgICAgIG9iai5tdWx0aUZhY3RvclNlc3Npb24ucGVuZGluZ0NyZWRlbnRpYWxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAob2JqLm11bHRpRmFjdG9yU2Vzc2lvbj8uaWRUb2tlbikge1xuICAgICAgICByZXR1cm4gTXVsdGlGYWN0b3JTZXNzaW9uSW1wbC5fZnJvbUlkdG9rZW4oXG4gICAgICAgICAgb2JqLm11bHRpRmFjdG9yU2Vzc2lvbi5pZFRva2VuXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHtcbiAgQXV0aCxcbiAgTXVsdGlGYWN0b3JSZXNvbHZlcixcbiAgVXNlckNyZWRlbnRpYWwsXG4gIE11bHRpRmFjdG9yRXJyb3Jcbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgX2Nhc3RBdXRoIH0gZnJvbSAnLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgVXNlckNyZWRlbnRpYWxJbXBsIH0gZnJvbSAnLi4vY29yZS91c2VyL3VzZXJfY3JlZGVudGlhbF9pbXBsJztcbmltcG9ydCB7IF9hc3NlcnQsIF9mYWlsIH0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBVc2VyQ3JlZGVudGlhbEludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwgfSBmcm9tICcuL21mYV9hc3NlcnRpb24nO1xuaW1wb3J0IHsgTXVsdGlGYWN0b3JFcnJvciBhcyBNdWx0aUZhY3RvckVycm9ySW50ZXJuYWwgfSBmcm9tICcuL21mYV9lcnJvcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckluZm9JbXBsIH0gZnJvbSAnLi9tZmFfaW5mbyc7XG5pbXBvcnQgeyBNdWx0aUZhY3RvclNlc3Npb25JbXBsIH0gZnJvbSAnLi9tZmFfc2Vzc2lvbic7XG5pbXBvcnQgeyBnZXRNb2R1bGFySW5zdGFuY2UgfSBmcm9tICdAZmlyZWJhc2UvdXRpbCc7XG5pbXBvcnQgeyBPcGVyYXRpb25UeXBlIH0gZnJvbSAnLi4vbW9kZWwvZW51bXMnO1xuXG5leHBvcnQgY2xhc3MgTXVsdGlGYWN0b3JSZXNvbHZlckltcGwgaW1wbGVtZW50cyBNdWx0aUZhY3RvclJlc29sdmVyIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBzZXNzaW9uOiBNdWx0aUZhY3RvclNlc3Npb25JbXBsLFxuICAgIHJlYWRvbmx5IGhpbnRzOiBNdWx0aUZhY3RvckluZm9JbXBsW10sXG4gICAgcHJpdmF0ZSByZWFkb25seSBzaWduSW5SZXNvbHZlcjogKFxuICAgICAgYXNzZXJ0aW9uOiBNdWx0aUZhY3RvckFzc2VydGlvbkltcGxcbiAgICApID0+IFByb21pc2U8VXNlckNyZWRlbnRpYWxJbnRlcm5hbD5cbiAgKSB7fVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tRXJyb3IoXG4gICAgYXV0aEV4dGVybjogQXV0aCxcbiAgICBlcnJvcjogTXVsdGlGYWN0b3JFcnJvckludGVybmFsXG4gICk6IE11bHRpRmFjdG9yUmVzb2x2ZXJJbXBsIHtcbiAgICBjb25zdCBhdXRoID0gX2Nhc3RBdXRoKGF1dGhFeHRlcm4pO1xuICAgIGNvbnN0IHNlcnZlclJlc3BvbnNlID0gZXJyb3IuY3VzdG9tRGF0YS5fc2VydmVyUmVzcG9uc2U7XG4gICAgY29uc3QgaGludHMgPSAoc2VydmVyUmVzcG9uc2UubWZhSW5mbyB8fCBbXSkubWFwKGVucm9sbG1lbnQgPT5cbiAgICAgIE11bHRpRmFjdG9ySW5mb0ltcGwuX2Zyb21TZXJ2ZXJSZXNwb25zZShhdXRoLCBlbnJvbGxtZW50KVxuICAgICk7XG5cbiAgICBfYXNzZXJ0KFxuICAgICAgc2VydmVyUmVzcG9uc2UubWZhUGVuZGluZ0NyZWRlbnRpYWwsXG4gICAgICBhdXRoLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwuX2Zyb21NZmFQZW5kaW5nQ3JlZGVudGlhbChcbiAgICAgIHNlcnZlclJlc3BvbnNlLm1mYVBlbmRpbmdDcmVkZW50aWFsXG4gICAgKTtcblxuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JSZXNvbHZlckltcGwoXG4gICAgICBzZXNzaW9uLFxuICAgICAgaGludHMsXG4gICAgICBhc3luYyAoXG4gICAgICAgIGFzc2VydGlvbjogTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsXG4gICAgICApOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsSW50ZXJuYWw+ID0+IHtcbiAgICAgICAgY29uc3QgbWZhUmVzcG9uc2UgPSBhd2FpdCBhc3NlcnRpb24uX3Byb2Nlc3MoYXV0aCwgc2Vzc2lvbik7XG4gICAgICAgIC8vIENsZWFyIG91dCB0aGUgdW5uZWVkZWQgZmllbGRzIGZyb20gdGhlIG9sZCBsb2dpbiByZXNwb25zZVxuICAgICAgICBkZWxldGUgc2VydmVyUmVzcG9uc2UubWZhSW5mbztcbiAgICAgICAgZGVsZXRlIHNlcnZlclJlc3BvbnNlLm1mYVBlbmRpbmdDcmVkZW50aWFsO1xuXG4gICAgICAgIC8vIFVzZSBpbiB0aGUgbmV3IHRva2VuICYgcmVmcmVzaCB0b2tlbiBpbiB0aGUgb2xkIHJlc3BvbnNlXG4gICAgICAgIGNvbnN0IGlkVG9rZW5SZXNwb25zZSA9IHtcbiAgICAgICAgICAuLi5zZXJ2ZXJSZXNwb25zZSxcbiAgICAgICAgICBpZFRva2VuOiBtZmFSZXNwb25zZS5pZFRva2VuLFxuICAgICAgICAgIHJlZnJlc2hUb2tlbjogbWZhUmVzcG9uc2UucmVmcmVzaFRva2VuXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gVE9ETzogd2Ugc2hvdWxkIGNvbGxhcHNlIHRoaXMgc3dpdGNoIHN0YXRlbWVudCBpbnRvIFVzZXJDcmVkZW50aWFsSW1wbC5fZm9yT3BlcmF0aW9uIGFuZCBoYXZlIGl0IHN1cHBvcnQgdGhlIFNJR05fSU4gY2FzZVxuICAgICAgICBzd2l0Y2ggKGVycm9yLm9wZXJhdGlvblR5cGUpIHtcbiAgICAgICAgICBjYXNlIE9wZXJhdGlvblR5cGUuU0lHTl9JTjpcbiAgICAgICAgICAgIGNvbnN0IHVzZXJDcmVkZW50aWFsID1cbiAgICAgICAgICAgICAgYXdhaXQgVXNlckNyZWRlbnRpYWxJbXBsLl9mcm9tSWRUb2tlblJlc3BvbnNlKFxuICAgICAgICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgICAgICAgZXJyb3Iub3BlcmF0aW9uVHlwZSxcbiAgICAgICAgICAgICAgICBpZFRva2VuUmVzcG9uc2VcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IGF1dGguX3VwZGF0ZUN1cnJlbnRVc2VyKHVzZXJDcmVkZW50aWFsLnVzZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHVzZXJDcmVkZW50aWFsO1xuICAgICAgICAgIGNhc2UgT3BlcmF0aW9uVHlwZS5SRUFVVEhFTlRJQ0FURTpcbiAgICAgICAgICAgIF9hc3NlcnQoZXJyb3IudXNlciwgYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgICAgICAgICByZXR1cm4gVXNlckNyZWRlbnRpYWxJbXBsLl9mb3JPcGVyYXRpb24oXG4gICAgICAgICAgICAgIGVycm9yLnVzZXIsXG4gICAgICAgICAgICAgIGVycm9yLm9wZXJhdGlvblR5cGUsXG4gICAgICAgICAgICAgIGlkVG9rZW5SZXNwb25zZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgX2ZhaWwoYXV0aCwgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgYXN5bmMgcmVzb2x2ZVNpZ25JbihcbiAgICBhc3NlcnRpb25FeHRlcm46IE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbFxuICApOiBQcm9taXNlPFVzZXJDcmVkZW50aWFsPiB7XG4gICAgY29uc3QgYXNzZXJ0aW9uID0gYXNzZXJ0aW9uRXh0ZXJuIGFzIE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbDtcbiAgICByZXR1cm4gdGhpcy5zaWduSW5SZXNvbHZlcihhc3NlcnRpb24pO1xuICB9XG59XG5cbi8qKlxuICogUHJvdmlkZXMgYSB7QGxpbmsgTXVsdGlGYWN0b3JSZXNvbHZlcn0gc3VpdGFibGUgZm9yIGNvbXBsZXRpb24gb2YgYVxuICogbXVsdGktZmFjdG9yIGZsb3cuXG4gKlxuICogQHBhcmFtIGF1dGggLSBUaGUge0BsaW5rIEF1dGh9IGluc3RhbmNlLlxuICogQHBhcmFtIGVycm9yIC0gVGhlIHtAbGluayBNdWx0aUZhY3RvckVycm9yfSByYWlzZWQgZHVyaW5nIGEgc2lnbi1pbiwgb3JcbiAqIHJlYXV0aGVudGljYXRpb24gb3BlcmF0aW9uLlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE11bHRpRmFjdG9yUmVzb2x2ZXIoXG4gIGF1dGg6IEF1dGgsXG4gIGVycm9yOiBNdWx0aUZhY3RvckVycm9yXG4pOiBNdWx0aUZhY3RvclJlc29sdmVyIHtcbiAgY29uc3QgYXV0aE1vZHVsYXIgPSBnZXRNb2R1bGFySW5zdGFuY2UoYXV0aCk7XG4gIGNvbnN0IGVycm9ySW50ZXJuYWwgPSBlcnJvciBhcyBNdWx0aUZhY3RvckVycm9ySW50ZXJuYWw7XG4gIF9hc3NlcnQoXG4gICAgZXJyb3IuY3VzdG9tRGF0YS5vcGVyYXRpb25UeXBlLFxuICAgIGF1dGhNb2R1bGFyLFxuICAgIEF1dGhFcnJvckNvZGUuQVJHVU1FTlRfRVJST1JcbiAgKTtcbiAgX2Fzc2VydChcbiAgICBlcnJvckludGVybmFsLmN1c3RvbURhdGEuX3NlcnZlclJlc3BvbnNlPy5tZmFQZW5kaW5nQ3JlZGVudGlhbCxcbiAgICBhdXRoTW9kdWxhcixcbiAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICk7XG5cbiAgcmV0dXJuIE11bHRpRmFjdG9yUmVzb2x2ZXJJbXBsLl9mcm9tRXJyb3IoYXV0aE1vZHVsYXIsIGVycm9ySW50ZXJuYWwpO1xufVxuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEVuZHBvaW50LFxuICBIdHRwTWV0aG9kLFxuICBSZWNhcHRjaGFDbGllbnRUeXBlLFxuICBSZWNhcHRjaGFWZXJzaW9uLFxuICBfYWRkVGlkSWZOZWNlc3NhcnksXG4gIF9wZXJmb3JtQXBpUmVxdWVzdFxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBTaWduSW5XaXRoUGhvbmVOdW1iZXJSZXF1ZXN0IH0gZnJvbSAnLi4vYXV0aGVudGljYXRpb24vc21zJztcbmltcG9ydCB7IEZpbmFsaXplTWZhUmVzcG9uc2UgfSBmcm9tICcuLi9hdXRoZW50aWNhdGlvbi9tZmEnO1xuaW1wb3J0IHsgQXV0aEludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvYXV0aCc7XG5cbi8qKlxuICogTUZBIEluZm8gYXMgcmV0dXJuZWQgYnkgdGhlIEFQSS5cbiAqL1xuaW50ZXJmYWNlIEJhc2VNZmFFbnJvbGxtZW50IHtcbiAgbWZhRW5yb2xsbWVudElkOiBzdHJpbmc7XG4gIGVucm9sbGVkQXQ6IG51bWJlcjtcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQW4gTUZBIHByb3ZpZGVkIGJ5IFNNUyB2ZXJpZmljYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGhvbmVNZmFFbnJvbGxtZW50IGV4dGVuZHMgQmFzZU1mYUVucm9sbG1lbnQge1xuICBwaG9uZUluZm86IHN0cmluZztcbn1cblxuLyoqXG4gKiBBbiBNRkEgcHJvdmlkZWQgYnkgVE9UUCAoVGltZS1iYXNlZCBPbmUgVGltZSBQYXNzd29yZCkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVG90cE1mYUVucm9sbG1lbnQgZXh0ZW5kcyBCYXNlTWZhRW5yb2xsbWVudCB7fVxuXG4vKipcbiAqIE1mYUVucm9sbG1lbnQgY2FuIGJlIGFueSBzdWJ0eXBlIG9mIEJhc2VNZmFFbnJvbGxtZW50LCBjdXJyZW50bHkgb25seSBQaG9uZU1mYUVucm9sbG1lbnQgYW5kIFRvdHBNZmFFbnJvbGxtZW50IGFyZSBzdXBwb3J0ZWQuXG4gKi9cbmV4cG9ydCB0eXBlIE1mYUVucm9sbG1lbnQgPSBQaG9uZU1mYUVucm9sbG1lbnQgfCBUb3RwTWZhRW5yb2xsbWVudDtcblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFBob25lTWZhRW5yb2xsbWVudFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHBob25lRW5yb2xsbWVudEluZm86IHtcbiAgICBwaG9uZU51bWJlcjogc3RyaW5nO1xuICAgIC8vIHJlQ0FQVENIQSB2MiB0b2tlblxuICAgIHJlY2FwdGNoYVRva2VuPzogc3RyaW5nO1xuICAgIC8vIHJlQ0FQVENIQSBFbnRlcnByaXNlIHRva2VuXG4gICAgY2FwdGNoYVJlc3BvbnNlPzogc3RyaW5nO1xuICAgIGNsaWVudFR5cGU/OiBSZWNhcHRjaGFDbGllbnRUeXBlO1xuICAgIHJlY2FwdGNoYVZlcnNpb24/OiBSZWNhcHRjaGFWZXJzaW9uO1xuICB9O1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlIHtcbiAgcGhvbmVTZXNzaW9uSW5mbzoge1xuICAgIHNlc3Npb25JbmZvOiBzdHJpbmc7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydEVucm9sbFBob25lTWZhKFxuICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFN0YXJ0UGhvbmVNZmFFbnJvbGxtZW50UmVxdWVzdFxuKTogUHJvbWlzZTxTdGFydFBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgU3RhcnRQaG9uZU1mYUVucm9sbG1lbnRSZXF1ZXN0LFxuICAgIFN0YXJ0UGhvbmVNZmFFbnJvbGxtZW50UmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5TVEFSVF9NRkFfRU5ST0xMTUVOVCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIHBob25lVmVyaWZpY2F0aW9uSW5mbzogU2lnbkluV2l0aFBob25lTnVtYmVyUmVxdWVzdDtcbiAgZGlzcGxheU5hbWU/OiBzdHJpbmcgfCBudWxsO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlXG4gIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgZnVuY3Rpb24gZmluYWxpemVFbnJvbGxQaG9uZU1mYShcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICByZXF1ZXN0OiBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlcXVlc3Rcbik6IFByb21pc2U8RmluYWxpemVQaG9uZU1mYUVucm9sbG1lbnRSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIEZpbmFsaXplUGhvbmVNZmFFbnJvbGxtZW50UmVxdWVzdCxcbiAgICBGaW5hbGl6ZVBob25lTWZhRW5yb2xsbWVudFJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuRklOQUxJWkVfTUZBX0VOUk9MTE1FTlQsXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXF1ZXN0IHtcbiAgaWRUb2tlbjogc3RyaW5nO1xuICB0b3RwRW5yb2xsbWVudEluZm86IHt9O1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2Uge1xuICB0b3RwU2Vzc2lvbkluZm86IHtcbiAgICBzaGFyZWRTZWNyZXRLZXk6IHN0cmluZztcbiAgICB2ZXJpZmljYXRpb25Db2RlTGVuZ3RoOiBudW1iZXI7XG4gICAgaGFzaGluZ0FsZ29yaXRobTogc3RyaW5nO1xuICAgIHBlcmlvZFNlYzogbnVtYmVyO1xuICAgIHNlc3Npb25JbmZvOiBzdHJpbmc7XG4gICAgZmluYWxpemVFbnJvbGxtZW50VGltZTogbnVtYmVyO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRFbnJvbGxUb3RwTWZhKFxuICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gIHJlcXVlc3Q6IFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXF1ZXN0XG4pOiBQcm9taXNlPFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZT4ge1xuICByZXR1cm4gX3BlcmZvcm1BcGlSZXF1ZXN0PFxuICAgIFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXF1ZXN0LFxuICAgIFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZVxuICA+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LlNUQVJUX01GQV9FTlJPTExNRU5ULFxuICAgIF9hZGRUaWRJZk5lY2Vzc2FyeShhdXRoLCByZXF1ZXN0KVxuICApO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRvdHBWZXJpZmljYXRpb25JbmZvIHtcbiAgc2Vzc2lvbkluZm86IHN0cmluZztcbiAgdmVyaWZpY2F0aW9uQ29kZTogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVxdWVzdCB7XG4gIGlkVG9rZW46IHN0cmluZztcbiAgdG90cFZlcmlmaWNhdGlvbkluZm86IFRvdHBWZXJpZmljYXRpb25JbmZvO1xuICBkaXNwbGF5TmFtZT86IHN0cmluZyB8IG51bGw7XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbmFsaXplVG90cE1mYUVucm9sbG1lbnRSZXNwb25zZVxuICBleHRlbmRzIEZpbmFsaXplTWZhUmVzcG9uc2Uge31cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmFsaXplRW5yb2xsVG90cE1mYShcbiAgYXV0aDogQXV0aEludGVybmFsLFxuICByZXF1ZXN0OiBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVxdWVzdFxuKTogUHJvbWlzZTxGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxcbiAgICBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVxdWVzdCxcbiAgICBGaW5hbGl6ZVRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2VcbiAgPihcbiAgICBhdXRoLFxuICAgIEh0dHBNZXRob2QuUE9TVCxcbiAgICBFbmRwb2ludC5GSU5BTElaRV9NRkFfRU5ST0xMTUVOVCxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXaXRoZHJhd01mYVJlcXVlc3Qge1xuICBpZFRva2VuOiBzdHJpbmc7XG4gIG1mYUVucm9sbG1lbnRJZDogc3RyaW5nO1xuICB0ZW5hbnRJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXaXRoZHJhd01mYVJlc3BvbnNlIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgZnVuY3Rpb24gd2l0aGRyYXdNZmEoXG4gIGF1dGg6IEF1dGhJbnRlcm5hbCxcbiAgcmVxdWVzdDogV2l0aGRyYXdNZmFSZXF1ZXN0XG4pOiBQcm9taXNlPFdpdGhkcmF3TWZhUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxXaXRoZHJhd01mYVJlcXVlc3QsIFdpdGhkcmF3TWZhUmVzcG9uc2U+KFxuICAgIGF1dGgsXG4gICAgSHR0cE1ldGhvZC5QT1NULFxuICAgIEVuZHBvaW50LldJVEhEUkFXX01GQSxcbiAgICBfYWRkVGlkSWZOZWNlc3NhcnkoYXV0aCwgcmVxdWVzdClcbiAgKTtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHtcbiAgTXVsdGlGYWN0b3JBc3NlcnRpb24sXG4gIE11bHRpRmFjdG9ySW5mbyxcbiAgTXVsdGlGYWN0b3JTZXNzaW9uLFxuICBNdWx0aUZhY3RvclVzZXIsXG4gIFVzZXJcbn0gZnJvbSAnLi4vbW9kZWwvcHVibGljX3R5cGVzJztcblxuaW1wb3J0IHsgd2l0aGRyYXdNZmEgfSBmcm9tICcuLi9hcGkvYWNjb3VudF9tYW5hZ2VtZW50L21mYSc7XG5pbXBvcnQgeyBfbG9nb3V0SWZJbnZhbGlkYXRlZCB9IGZyb20gJy4uL2NvcmUvdXNlci9pbnZhbGlkYXRpb24nO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwgfSBmcm9tICcuL21mYV9hc3NlcnRpb24nO1xuaW1wb3J0IHsgTXVsdGlGYWN0b3JJbmZvSW1wbCB9IGZyb20gJy4vbWZhX2luZm8nO1xuaW1wb3J0IHsgTXVsdGlGYWN0b3JTZXNzaW9uSW1wbCB9IGZyb20gJy4vbWZhX3Nlc3Npb24nO1xuaW1wb3J0IHsgZ2V0TW9kdWxhckluc3RhbmNlIH0gZnJvbSAnQGZpcmViYXNlL3V0aWwnO1xuXG5leHBvcnQgY2xhc3MgTXVsdGlGYWN0b3JVc2VySW1wbCBpbXBsZW1lbnRzIE11bHRpRmFjdG9yVXNlciB7XG4gIGVucm9sbGVkRmFjdG9yczogTXVsdGlGYWN0b3JJbmZvW10gPSBbXTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHVzZXI6IFVzZXJJbnRlcm5hbCkge1xuICAgIHVzZXIuX29uUmVsb2FkKHVzZXJJbmZvID0+IHtcbiAgICAgIGlmICh1c2VySW5mby5tZmFJbmZvKSB7XG4gICAgICAgIHRoaXMuZW5yb2xsZWRGYWN0b3JzID0gdXNlckluZm8ubWZhSW5mby5tYXAoZW5yb2xsbWVudCA9PlxuICAgICAgICAgIE11bHRpRmFjdG9ySW5mb0ltcGwuX2Zyb21TZXJ2ZXJSZXNwb25zZSh1c2VyLmF1dGgsIGVucm9sbG1lbnQpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgX2Zyb21Vc2VyKHVzZXI6IFVzZXJJbnRlcm5hbCk6IE11bHRpRmFjdG9yVXNlckltcGwge1xuICAgIHJldHVybiBuZXcgTXVsdGlGYWN0b3JVc2VySW1wbCh1c2VyKTtcbiAgfVxuXG4gIGFzeW5jIGdldFNlc3Npb24oKTogUHJvbWlzZTxNdWx0aUZhY3RvclNlc3Npb24+IHtcbiAgICByZXR1cm4gTXVsdGlGYWN0b3JTZXNzaW9uSW1wbC5fZnJvbUlkdG9rZW4oXG4gICAgICBhd2FpdCB0aGlzLnVzZXIuZ2V0SWRUb2tlbigpLFxuICAgICAgdGhpcy51c2VyXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGVucm9sbChcbiAgICBhc3NlcnRpb25FeHRlcm46IE11bHRpRmFjdG9yQXNzZXJ0aW9uLFxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhc3NlcnRpb24gPSBhc3NlcnRpb25FeHRlcm4gYXMgTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsO1xuICAgIGNvbnN0IHNlc3Npb24gPSAoYXdhaXQgdGhpcy5nZXRTZXNzaW9uKCkpIGFzIE11bHRpRmFjdG9yU2Vzc2lvbkltcGw7XG4gICAgY29uc3QgZmluYWxpemVNZmFSZXNwb25zZSA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgICAgdGhpcy51c2VyLFxuICAgICAgYXNzZXJ0aW9uLl9wcm9jZXNzKHRoaXMudXNlci5hdXRoLCBzZXNzaW9uLCBkaXNwbGF5TmFtZSlcbiAgICApO1xuICAgIC8vIE5ldyB0b2tlbnMgd2lsbCBiZSBpc3N1ZWQgYWZ0ZXIgZW5yb2xsbWVudCBvZiB0aGUgbmV3IHNlY29uZCBmYWN0b3JzLlxuICAgIC8vIFRoZXkgbmVlZCB0byBiZSB1cGRhdGVkIG9uIHRoZSB1c2VyLlxuICAgIGF3YWl0IHRoaXMudXNlci5fdXBkYXRlVG9rZW5zSWZOZWNlc3NhcnkoZmluYWxpemVNZmFSZXNwb25zZSk7XG4gICAgLy8gVGhlIHVzZXIgbmVlZHMgdG8gYmUgcmVsb2FkZWQgdG8gZ2V0IHRoZSBuZXcgbXVsdGktZmFjdG9yIGluZm9ybWF0aW9uXG4gICAgLy8gZnJvbSBzZXJ2ZXIuIFVTRVJfUkVMT0FERUQgZXZlbnQgd2lsbCBiZSB0cmlnZ2VyZWQgYW5kIGBlbnJvbGxlZEZhY3RvcnNgXG4gICAgLy8gd2lsbCBiZSB1cGRhdGVkLlxuICAgIHJldHVybiB0aGlzLnVzZXIucmVsb2FkKCk7XG4gIH1cblxuICBhc3luYyB1bmVucm9sbChpbmZvT3JVaWQ6IE11bHRpRmFjdG9ySW5mbyB8IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG1mYUVucm9sbG1lbnRJZCA9XG4gICAgICB0eXBlb2YgaW5mb09yVWlkID09PSAnc3RyaW5nJyA/IGluZm9PclVpZCA6IGluZm9PclVpZC51aWQ7XG4gICAgY29uc3QgaWRUb2tlbiA9IGF3YWl0IHRoaXMudXNlci5nZXRJZFRva2VuKCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGlkVG9rZW5SZXNwb25zZSA9IGF3YWl0IF9sb2dvdXRJZkludmFsaWRhdGVkKFxuICAgICAgICB0aGlzLnVzZXIsXG4gICAgICAgIHdpdGhkcmF3TWZhKHRoaXMudXNlci5hdXRoLCB7XG4gICAgICAgICAgaWRUb2tlbixcbiAgICAgICAgICBtZmFFbnJvbGxtZW50SWRcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICAvLyBSZW1vdmUgdGhlIHNlY29uZCBmYWN0b3IgZnJvbSB0aGUgdXNlcidzIGxpc3QuXG4gICAgICB0aGlzLmVucm9sbGVkRmFjdG9ycyA9IHRoaXMuZW5yb2xsZWRGYWN0b3JzLmZpbHRlcihcbiAgICAgICAgKHsgdWlkIH0pID0+IHVpZCAhPT0gbWZhRW5yb2xsbWVudElkXG4gICAgICApO1xuICAgICAgLy8gRGVwZW5kaW5nIG9uIHdoZXRoZXIgdGhlIGJhY2tlbmQgZGVjaWRlZCB0byByZXZva2UgdGhlIHVzZXIncyBzZXNzaW9uLFxuICAgICAgLy8gdGhlIHRva2VuUmVzcG9uc2UgbWF5IGJlIGVtcHR5LiBJZiB0aGUgdG9rZW5zIHdlcmUgbm90IHVwZGF0ZWQgKGFuZCB0aGV5XG4gICAgICAvLyBhcmUgbm93IGludmFsaWQpLCByZWxvYWRpbmcgdGhlIHVzZXIgd2lsbCBkaXNjb3ZlciB0aGlzIGFuZCBpbnZhbGlkYXRlXG4gICAgICAvLyB0aGUgdXNlcidzIHN0YXRlIGFjY29yZGluZ2x5LlxuICAgICAgYXdhaXQgdGhpcy51c2VyLl91cGRhdGVUb2tlbnNJZk5lY2Vzc2FyeShpZFRva2VuUmVzcG9uc2UpO1xuICAgICAgYXdhaXQgdGhpcy51c2VyLnJlbG9hZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IG11bHRpRmFjdG9yVXNlckNhY2hlID0gbmV3IFdlYWtNYXA8VXNlciwgTXVsdGlGYWN0b3JVc2VyPigpO1xuXG4vKipcbiAqIFRoZSB7QGxpbmsgTXVsdGlGYWN0b3JVc2VyfSBjb3JyZXNwb25kaW5nIHRvIHRoZSB1c2VyLlxuICpcbiAqIEByZW1hcmtzXG4gKiBUaGlzIGlzIHVzZWQgdG8gYWNjZXNzIGFsbCBtdWx0aS1mYWN0b3IgcHJvcGVydGllcyBhbmQgb3BlcmF0aW9ucyByZWxhdGVkIHRvIHRoZSB1c2VyLlxuICpcbiAqIEBwYXJhbSB1c2VyIC0gVGhlIHVzZXIuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlGYWN0b3IodXNlcjogVXNlcik6IE11bHRpRmFjdG9yVXNlciB7XG4gIGNvbnN0IHVzZXJNb2R1bGFyID0gZ2V0TW9kdWxhckluc3RhbmNlKHVzZXIpO1xuICBpZiAoIW11bHRpRmFjdG9yVXNlckNhY2hlLmhhcyh1c2VyTW9kdWxhcikpIHtcbiAgICBtdWx0aUZhY3RvclVzZXJDYWNoZS5zZXQoXG4gICAgICB1c2VyTW9kdWxhcixcbiAgICAgIE11bHRpRmFjdG9yVXNlckltcGwuX2Zyb21Vc2VyKHVzZXJNb2R1bGFyIGFzIFVzZXJJbnRlcm5hbClcbiAgICApO1xuICB9XG4gIHJldHVybiBtdWx0aUZhY3RvclVzZXJDYWNoZS5nZXQodXNlck1vZHVsYXIpITtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBVbnN1YnNjcmliZSB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcbmltcG9ydCB7IEZpcmViYXNlQXV0aEludGVybmFsIH0gZnJvbSAnQGZpcmViYXNlL2F1dGgtaW50ZXJvcC10eXBlcyc7XG5cbmltcG9ydCB7IEF1dGhJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgVXNlckludGVybmFsIH0gZnJvbSAnLi4vLi4vbW9kZWwvdXNlcic7XG5pbXBvcnQgeyBfYXNzZXJ0IH0gZnJvbSAnLi4vdXRpbC9hc3NlcnQnO1xuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbmludGVyZmFjZSBUb2tlbkxpc3RlbmVyIHtcbiAgKHRvazogc3RyaW5nIHwgbnVsbCk6IHVua25vd247XG59XG5cbmV4cG9ydCBjbGFzcyBBdXRoSW50ZXJvcCBpbXBsZW1lbnRzIEZpcmViYXNlQXV0aEludGVybmFsIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcm5hbExpc3RlbmVyczogTWFwPFRva2VuTGlzdGVuZXIsIFVuc3Vic2NyaWJlPiA9XG4gICAgbmV3IE1hcCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgYXV0aDogQXV0aEludGVybmFsKSB7fVxuXG4gIGdldFVpZCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICB0aGlzLmFzc2VydEF1dGhDb25maWd1cmVkKCk7XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5jdXJyZW50VXNlcj8udWlkIHx8IG51bGw7XG4gIH1cblxuICBhc3luYyBnZXRUb2tlbihcbiAgICBmb3JjZVJlZnJlc2g/OiBib29sZWFuXG4gICk6IFByb21pc2U8eyBhY2Nlc3NUb2tlbjogc3RyaW5nIH0gfCBudWxsPiB7XG4gICAgdGhpcy5hc3NlcnRBdXRoQ29uZmlndXJlZCgpO1xuICAgIGF3YWl0IHRoaXMuYXV0aC5faW5pdGlhbGl6YXRpb25Qcm9taXNlO1xuICAgIGlmICghdGhpcy5hdXRoLmN1cnJlbnRVc2VyKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IGF3YWl0IHRoaXMuYXV0aC5jdXJyZW50VXNlci5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG4gICAgcmV0dXJuIHsgYWNjZXNzVG9rZW4gfTtcbiAgfVxuXG4gIGFkZEF1dGhUb2tlbkxpc3RlbmVyKGxpc3RlbmVyOiBUb2tlbkxpc3RlbmVyKTogdm9pZCB7XG4gICAgdGhpcy5hc3NlcnRBdXRoQ29uZmlndXJlZCgpO1xuICAgIGlmICh0aGlzLmludGVybmFsTGlzdGVuZXJzLmhhcyhsaXN0ZW5lcikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1bnN1YnNjcmliZSA9IHRoaXMuYXV0aC5vbklkVG9rZW5DaGFuZ2VkKHVzZXIgPT4ge1xuICAgICAgbGlzdGVuZXIoXG4gICAgICAgICh1c2VyIGFzIFVzZXJJbnRlcm5hbCB8IG51bGwpPy5zdHNUb2tlbk1hbmFnZXIuYWNjZXNzVG9rZW4gfHwgbnVsbFxuICAgICAgKTtcbiAgICB9KTtcbiAgICB0aGlzLmludGVybmFsTGlzdGVuZXJzLnNldChsaXN0ZW5lciwgdW5zdWJzY3JpYmUpO1xuICAgIHRoaXMudXBkYXRlUHJvYWN0aXZlUmVmcmVzaCgpO1xuICB9XG5cbiAgcmVtb3ZlQXV0aFRva2VuTGlzdGVuZXIobGlzdGVuZXI6IFRva2VuTGlzdGVuZXIpOiB2b2lkIHtcbiAgICB0aGlzLmFzc2VydEF1dGhDb25maWd1cmVkKCk7XG4gICAgY29uc3QgdW5zdWJzY3JpYmUgPSB0aGlzLmludGVybmFsTGlzdGVuZXJzLmdldChsaXN0ZW5lcik7XG4gICAgaWYgKCF1bnN1YnNjcmliZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuaW50ZXJuYWxMaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICB1bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudXBkYXRlUHJvYWN0aXZlUmVmcmVzaCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnRBdXRoQ29uZmlndXJlZCgpOiB2b2lkIHtcbiAgICBfYXNzZXJ0KFxuICAgICAgdGhpcy5hdXRoLl9pbml0aWFsaXphdGlvblByb21pc2UsXG4gICAgICBBdXRoRXJyb3JDb2RlLkRFUEVOREVOVF9TREtfSU5JVF9CRUZPUkVfQVVUSFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVByb2FjdGl2ZVJlZnJlc2goKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW50ZXJuYWxMaXN0ZW5lcnMuc2l6ZSA+IDApIHtcbiAgICAgIHRoaXMuYXV0aC5fc3RhcnRQcm9hY3RpdmVSZWZyZXNoKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXV0aC5fc3RvcFByb2FjdGl2ZVJlZnJlc2goKTtcbiAgICB9XG4gIH1cbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBfcmVnaXN0ZXJDb21wb25lbnQsIHJlZ2lzdGVyVmVyc2lvbiB9IGZyb20gJ0BmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRUeXBlLFxuICBJbnN0YW50aWF0aW9uTW9kZVxufSBmcm9tICdAZmlyZWJhc2UvY29tcG9uZW50JztcblxuaW1wb3J0IHsgbmFtZSwgdmVyc2lvbiB9IGZyb20gJy4uLy4uLy4uL3BhY2thZ2UuanNvbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IF9hc3NlcnQgfSBmcm9tICcuLi91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBfZ2V0Q2xpZW50VmVyc2lvbiwgQ2xpZW50UGxhdGZvcm0gfSBmcm9tICcuLi91dGlsL3ZlcnNpb24nO1xuaW1wb3J0IHsgX2Nhc3RBdXRoLCBBdXRoSW1wbCwgRGVmYXVsdENvbmZpZyB9IGZyb20gJy4vYXV0aF9pbXBsJztcbmltcG9ydCB7IEF1dGhJbnRlcm9wIH0gZnJvbSAnLi9maXJlYmFzZV9pbnRlcm5hbCc7XG5pbXBvcnQgeyBDb25maWdJbnRlcm5hbCB9IGZyb20gJy4uLy4uL21vZGVsL2F1dGgnO1xuaW1wb3J0IHsgRGVwZW5kZW5jaWVzIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IF9pbml0aWFsaXplQXV0aEluc3RhbmNlIH0gZnJvbSAnLi9pbml0aWFsaXplJztcblxuZXhwb3J0IGNvbnN0IGVudW0gX0NvbXBvbmVudE5hbWUge1xuICBBVVRIID0gJ2F1dGgnLFxuICBBVVRIX0lOVEVSTkFMID0gJ2F1dGgtaW50ZXJuYWwnXG59XG5cbmZ1bmN0aW9uIGdldFZlcnNpb25Gb3JQbGF0Zm9ybShcbiAgY2xpZW50UGxhdGZvcm06IENsaWVudFBsYXRmb3JtXG4pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBzd2l0Y2ggKGNsaWVudFBsYXRmb3JtKSB7XG4gICAgY2FzZSBDbGllbnRQbGF0Zm9ybS5OT0RFOlxuICAgICAgcmV0dXJuICdub2RlJztcbiAgICBjYXNlIENsaWVudFBsYXRmb3JtLlJFQUNUX05BVElWRTpcbiAgICAgIHJldHVybiAncm4nO1xuICAgIGNhc2UgQ2xpZW50UGxhdGZvcm0uV09SS0VSOlxuICAgICAgcmV0dXJuICd3ZWJ3b3JrZXInO1xuICAgIGNhc2UgQ2xpZW50UGxhdGZvcm0uQ09SRE9WQTpcbiAgICAgIHJldHVybiAnY29yZG92YSc7XG4gICAgY2FzZSBDbGllbnRQbGF0Zm9ybS5XRUJfRVhURU5TSU9OOlxuICAgICAgcmV0dXJuICd3ZWItZXh0ZW5zaW9uJztcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKiogQGludGVybmFsICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJBdXRoKGNsaWVudFBsYXRmb3JtOiBDbGllbnRQbGF0Zm9ybSk6IHZvaWQge1xuICBfcmVnaXN0ZXJDb21wb25lbnQoXG4gICAgbmV3IENvbXBvbmVudChcbiAgICAgIF9Db21wb25lbnROYW1lLkFVVEgsXG4gICAgICAoY29udGFpbmVyLCB7IG9wdGlvbnM6IGRlcHMgfTogeyBvcHRpb25zPzogRGVwZW5kZW5jaWVzIH0pID0+IHtcbiAgICAgICAgY29uc3QgYXBwID0gY29udGFpbmVyLmdldFByb3ZpZGVyKCdhcHAnKS5nZXRJbW1lZGlhdGUoKSE7XG4gICAgICAgIGNvbnN0IGhlYXJ0YmVhdFNlcnZpY2VQcm92aWRlciA9XG4gICAgICAgICAgY29udGFpbmVyLmdldFByb3ZpZGVyPCdoZWFydGJlYXQnPignaGVhcnRiZWF0Jyk7XG4gICAgICAgIGNvbnN0IGFwcENoZWNrU2VydmljZVByb3ZpZGVyID1cbiAgICAgICAgICBjb250YWluZXIuZ2V0UHJvdmlkZXI8J2FwcC1jaGVjay1pbnRlcm5hbCc+KCdhcHAtY2hlY2staW50ZXJuYWwnKTtcbiAgICAgICAgY29uc3QgeyBhcGlLZXksIGF1dGhEb21haW4gfSA9IGFwcC5vcHRpb25zO1xuXG4gICAgICAgIF9hc3NlcnQoXG4gICAgICAgICAgYXBpS2V5ICYmICFhcGlLZXkuaW5jbHVkZXMoJzonKSxcbiAgICAgICAgICBBdXRoRXJyb3JDb2RlLklOVkFMSURfQVBJX0tFWSxcbiAgICAgICAgICB7IGFwcE5hbWU6IGFwcC5uYW1lIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBjb25maWc6IENvbmZpZ0ludGVybmFsID0ge1xuICAgICAgICAgIGFwaUtleSxcbiAgICAgICAgICBhdXRoRG9tYWluLFxuICAgICAgICAgIGNsaWVudFBsYXRmb3JtLFxuICAgICAgICAgIGFwaUhvc3Q6IERlZmF1bHRDb25maWcuQVBJX0hPU1QsXG4gICAgICAgICAgdG9rZW5BcGlIb3N0OiBEZWZhdWx0Q29uZmlnLlRPS0VOX0FQSV9IT1NULFxuICAgICAgICAgIGFwaVNjaGVtZTogRGVmYXVsdENvbmZpZy5BUElfU0NIRU1FLFxuICAgICAgICAgIHNka0NsaWVudFZlcnNpb246IF9nZXRDbGllbnRWZXJzaW9uKGNsaWVudFBsYXRmb3JtKVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGF1dGhJbnN0YW5jZSA9IG5ldyBBdXRoSW1wbChcbiAgICAgICAgICBhcHAsXG4gICAgICAgICAgaGVhcnRiZWF0U2VydmljZVByb3ZpZGVyLFxuICAgICAgICAgIGFwcENoZWNrU2VydmljZVByb3ZpZGVyLFxuICAgICAgICAgIGNvbmZpZ1xuICAgICAgICApO1xuICAgICAgICBfaW5pdGlhbGl6ZUF1dGhJbnN0YW5jZShhdXRoSW5zdGFuY2UsIGRlcHMpO1xuXG4gICAgICAgIHJldHVybiBhdXRoSW5zdGFuY2U7XG4gICAgICB9LFxuICAgICAgQ29tcG9uZW50VHlwZS5QVUJMSUNcbiAgICApXG4gICAgICAvKipcbiAgICAgICAqIEF1dGggY2FuIG9ubHkgYmUgaW5pdGlhbGl6ZWQgYnkgZXhwbGljaXRseSBjYWxsaW5nIGdldEF1dGgoKSBvciBpbml0aWFsaXplQXV0aCgpXG4gICAgICAgKiBGb3Igd2h5IHdlIGRvIHRoaXMsIFNlZSBnby9maXJlYmFzZS1uZXh0LWF1dGgtaW5pdFxuICAgICAgICovXG4gICAgICAuc2V0SW5zdGFudGlhdGlvbk1vZGUoSW5zdGFudGlhdGlvbk1vZGUuRVhQTElDSVQpXG4gICAgICAvKipcbiAgICAgICAqIEJlY2F1c2UgYWxsIGZpcmViYXNlIHByb2R1Y3RzIHRoYXQgZGVwZW5kIG9uIGF1dGggZGVwZW5kIG9uIGF1dGgtaW50ZXJuYWwgZGlyZWN0bHksXG4gICAgICAgKiB3ZSBuZWVkIHRvIGluaXRpYWxpemUgYXV0aC1pbnRlcm5hbCBhZnRlciBhdXRoIGlzIGluaXRpYWxpemVkIHRvIG1ha2UgaXQgYXZhaWxhYmxlIHRvIG90aGVyIGZpcmViYXNlIHByb2R1Y3RzLlxuICAgICAgICovXG4gICAgICAuc2V0SW5zdGFuY2VDcmVhdGVkQ2FsbGJhY2soXG4gICAgICAgIChjb250YWluZXIsIF9pbnN0YW5jZUlkZW50aWZpZXIsIF9pbnN0YW5jZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGF1dGhJbnRlcm5hbFByb3ZpZGVyID0gY29udGFpbmVyLmdldFByb3ZpZGVyKFxuICAgICAgICAgICAgX0NvbXBvbmVudE5hbWUuQVVUSF9JTlRFUk5BTFxuICAgICAgICAgICk7XG4gICAgICAgICAgYXV0aEludGVybmFsUHJvdmlkZXIuaW5pdGlhbGl6ZSgpO1xuICAgICAgICB9XG4gICAgICApXG4gICk7XG5cbiAgX3JlZ2lzdGVyQ29tcG9uZW50KFxuICAgIG5ldyBDb21wb25lbnQoXG4gICAgICBfQ29tcG9uZW50TmFtZS5BVVRIX0lOVEVSTkFMLFxuICAgICAgY29udGFpbmVyID0+IHtcbiAgICAgICAgY29uc3QgYXV0aCA9IF9jYXN0QXV0aChcbiAgICAgICAgICBjb250YWluZXIuZ2V0UHJvdmlkZXIoX0NvbXBvbmVudE5hbWUuQVVUSCkuZ2V0SW1tZWRpYXRlKCkhXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiAoYXV0aCA9PiBuZXcgQXV0aEludGVyb3AoYXV0aCkpKGF1dGgpO1xuICAgICAgfSxcbiAgICAgIENvbXBvbmVudFR5cGUuUFJJVkFURVxuICAgICkuc2V0SW5zdGFudGlhdGlvbk1vZGUoSW5zdGFudGlhdGlvbk1vZGUuRVhQTElDSVQpXG4gICk7XG5cbiAgcmVnaXN0ZXJWZXJzaW9uKG5hbWUsIHZlcnNpb24sIGdldFZlcnNpb25Gb3JQbGF0Zm9ybShjbGllbnRQbGF0Zm9ybSkpO1xuICAvLyBCVUlMRF9UQVJHRVQgd2lsbCBiZSByZXBsYWNlZCBieSB2YWx1ZXMgbGlrZSBlc20sIGNqcywgZXRjIGR1cmluZyB0aGUgY29tcGlsYXRpb25cbiAgcmVnaXN0ZXJWZXJzaW9uKG5hbWUsIHZlcnNpb24sICdfX0JVSUxEX1RBUkdFVF9fJyk7XG59XG4iLCAiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQXV0aEVycm9yQ29kZSB9IGZyb20gJy4uL2NvcmUvZXJyb3JzJztcbmltcG9ydCB7IF9jcmVhdGVFcnJvciB9IGZyb20gJy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuXG5pbXBvcnQgeyBGaXJlYmFzZUFwcCwgZ2V0QXBwLCBfZ2V0UHJvdmlkZXIgfSBmcm9tICdAZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IEF1dGggfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuXG5pbXBvcnQgeyBpbml0aWFsaXplQXV0aCwgaW5NZW1vcnlQZXJzaXN0ZW5jZSwgY29ubmVjdEF1dGhFbXVsYXRvciB9IGZyb20gJy4uJztcbmltcG9ydCB7IHJlZ2lzdGVyQXV0aCB9IGZyb20gJy4uL2NvcmUvYXV0aC9yZWdpc3Rlcic7XG5pbXBvcnQgeyBDbGllbnRQbGF0Zm9ybSB9IGZyb20gJy4uL2NvcmUvdXRpbC92ZXJzaW9uJztcbmltcG9ydCB7IEF1dGhJbXBsIH0gZnJvbSAnLi4vY29yZS9hdXRoL2F1dGhfaW1wbCc7XG5cbmltcG9ydCB7IEZldGNoUHJvdmlkZXIgfSBmcm9tICcuLi9jb3JlL3V0aWwvZmV0Y2hfcHJvdmlkZXInO1xuaW1wb3J0IHsgZ2V0RGVmYXVsdEVtdWxhdG9ySG9zdCB9IGZyb20gJ0BmaXJlYmFzZS91dGlsJztcblxuLy8gSW5pdGlhbGl6ZSB0aGUgZmV0Y2ggcG9seWZpbGwsIHRoZSB0eXBlcyBhcmUgc2xpZ2h0bHkgb2ZmIHNvIGp1c3QgY2FzdCBhbmQgaG9wZSBmb3IgdGhlIGJlc3RcbkZldGNoUHJvdmlkZXIuaW5pdGlhbGl6ZShmZXRjaCwgSGVhZGVycywgUmVzcG9uc2UpO1xuXG4vLyBGaXJzdCwgd2Ugc2V0IHVwIHRoZSB2YXJpb3VzIHBsYXRmb3JtLXNwZWNpZmljIGZlYXR1cmVzIGZvciBOb2RlIChyZWdpc3RlclxuLy8gdGhlIHZlcnNpb24gYW5kIGRlY2xhcmUgdGhlIE5vZGUgZ2V0QXV0aCBmdW5jdGlvbilcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEF1dGgoYXBwOiBGaXJlYmFzZUFwcCA9IGdldEFwcCgpKTogQXV0aCB7XG4gIGNvbnN0IHByb3ZpZGVyID0gX2dldFByb3ZpZGVyKGFwcCwgJ2F1dGgnKTtcblxuICBpZiAocHJvdmlkZXIuaXNJbml0aWFsaXplZCgpKSB7XG4gICAgcmV0dXJuIHByb3ZpZGVyLmdldEltbWVkaWF0ZSgpO1xuICB9XG5cbiAgY29uc3QgYXV0aCA9IGluaXRpYWxpemVBdXRoKGFwcCk7XG5cbiAgY29uc3QgYXV0aEVtdWxhdG9ySG9zdCA9IGdldERlZmF1bHRFbXVsYXRvckhvc3QoJ2F1dGgnKTtcbiAgaWYgKGF1dGhFbXVsYXRvckhvc3QpIHtcbiAgICBjb25uZWN0QXV0aEVtdWxhdG9yKGF1dGgsIGBodHRwOi8vJHthdXRoRW11bGF0b3JIb3N0fWApO1xuICB9XG5cbiAgcmV0dXJuIGF1dGg7XG59XG5cbnJlZ2lzdGVyQXV0aChDbGllbnRQbGF0Zm9ybS5OT0RFKTtcblxuLy8gVGhlIHJlc3Qgb2YgdGhpcyBmaWxlIGNvbnRhaW5zIG5vLW9wcyBhbmQgZXJyb3JzIGZvciBicm93c2VyLXNwZWNpZmljXG4vLyBtZXRob2RzLiBXZSBrZWVwIHRoZSBicm93c2VyIGFuZCBOb2RlIGVudHJ5IHBvaW50cyB0aGUgc2FtZSwgYnV0IGZlYXR1cmVzXG4vLyB0aGF0IG9ubHkgd29yayBpbiBicm93c2VycyBhcmUgc2V0IHRvIGVpdGhlciBkbyBub3RoaW5nIChzZXRQZXJzaXN0ZW5jZSkgb3Jcbi8vIHRvIHJlamVjdCB3aXRoIGFuIGF1dGgvb3BlcmF0aW9uLW5vdC1zdXBwb3J0ZWQtaW4tdGhpcy1lbnZpcm9ubWVudCBlcnJvci5cbi8vIFRoZSBiZWxvdyBleHBvcnRzIGFyZSBwdWxsZWQgaW50byB0aGUgbWFpbiBlbnRyeSBwb2ludCBieSBhIHJvbGx1cCBhbGlhc1xuLy8gcGx1Z2luIChvdmVyd3JpdGluZyB0aGUgZGVmYXVsdCBicm93c2VyIGltcG9ydHMpLlxuXG4vKiogYXV0aC9vcGVyYXRpb24tbm90LXN1cHBvcnRlZC1pbi10aGlzLWVudmlyb25tZW50ICovXG5jb25zdCBOT1RfQVZBSUxBQkxFX0VSUk9SID0gX2NyZWF0ZUVycm9yKEF1dGhFcnJvckNvZGUuT1BFUkFUSU9OX05PVF9TVVBQT1JURUQpO1xuXG4vKiogUmVqZWN0IHdpdGggYXV0aC9vcGVyYXRpb24tbm90LXN1cHBvcnRlZC1pbi10aGlzLWVudmlyb25tZW50ICovXG5hc3luYyBmdW5jdGlvbiBmYWlsKCk6IFByb21pc2U8dm9pZD4ge1xuICB0aHJvdyBOT1RfQVZBSUxBQkxFX0VSUk9SO1xufVxuXG4vKipcbiAqIEEgY2xhc3Mgd2hpY2ggd2lsbCB0aHJvdyB3aXRoXG4gKiBhdXRoL29wZXJhdGlvbi1ub3Qtc3VwcG9ydGVkLWluLXRoaXMtZW52aXJvbm1lbnQgaWYgaW5zdGFudGlhdGVkXG4gKi9cbmNsYXNzIEZhaWxDbGFzcyB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRocm93IE5PVF9BVkFJTEFCTEVfRVJST1I7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGJyb3dzZXJMb2NhbFBlcnNpc3RlbmNlID0gaW5NZW1vcnlQZXJzaXN0ZW5jZTtcbmV4cG9ydCBjb25zdCBicm93c2VyU2Vzc2lvblBlcnNpc3RlbmNlID0gaW5NZW1vcnlQZXJzaXN0ZW5jZTtcbmV4cG9ydCBjb25zdCBicm93c2VyQ29va2llUGVyc2lzdGVuY2UgPSBpbk1lbW9yeVBlcnNpc3RlbmNlO1xuZXhwb3J0IGNvbnN0IGluZGV4ZWREQkxvY2FsUGVyc2lzdGVuY2UgPSBpbk1lbW9yeVBlcnNpc3RlbmNlO1xuZXhwb3J0IGNvbnN0IGJyb3dzZXJQb3B1cFJlZGlyZWN0UmVzb2x2ZXIgPSBOT1RfQVZBSUxBQkxFX0VSUk9SO1xuZXhwb3J0IGNvbnN0IFBob25lQXV0aFByb3ZpZGVyID0gRmFpbENsYXNzO1xuZXhwb3J0IGNvbnN0IHNpZ25JbldpdGhQaG9uZU51bWJlciA9IGZhaWw7XG5leHBvcnQgY29uc3QgbGlua1dpdGhQaG9uZU51bWJlciA9IGZhaWw7XG5leHBvcnQgY29uc3QgcmVhdXRoZW50aWNhdGVXaXRoUGhvbmVOdW1iZXIgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IHVwZGF0ZVBob25lTnVtYmVyID0gZmFpbDtcbmV4cG9ydCBjb25zdCBzaWduSW5XaXRoUG9wdXAgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IGxpbmtXaXRoUG9wdXAgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IHJlYXV0aGVudGljYXRlV2l0aFBvcHVwID0gZmFpbDtcbmV4cG9ydCBjb25zdCBzaWduSW5XaXRoUmVkaXJlY3QgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IGxpbmtXaXRoUmVkaXJlY3QgPSBmYWlsO1xuZXhwb3J0IGNvbnN0IHJlYXV0aGVudGljYXRlV2l0aFJlZGlyZWN0ID0gZmFpbDtcbmV4cG9ydCBjb25zdCBnZXRSZWRpcmVjdFJlc3VsdCA9IGZhaWw7XG5leHBvcnQgY29uc3QgUmVjYXB0Y2hhVmVyaWZpZXIgPSBGYWlsQ2xhc3M7XG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZyA9IGZhaWw7XG5leHBvcnQgY2xhc3MgUGhvbmVNdWx0aUZhY3RvckdlbmVyYXRvciB7XG4gIHN0YXRpYyBhc3NlcnRpb24oKTogdW5rbm93biB7XG4gICAgdGhyb3cgTk9UX0FWQUlMQUJMRV9FUlJPUjtcbiAgfVxufVxuXG4vLyBTZXQgcGVyc2lzdGVuY2Ugc2hvdWxkIG5vLW9wIGluc3RlYWQgb2YgZmFpbC4gQ2hhbmdpbmcgdGhlIHByb3RvdHlwZSB3aWxsXG4vLyBtYWtlIHN1cmUgYm90aCBzZXRQZXJzaXN0ZW5jZShhdXRoLCBwZXJzaXN0ZW5jZSkgYW5kXG4vLyBhdXRoLnNldFBlcnNpc3RlbmNlKHBlcnNpc3RlbmNlKSBhcmUgY292ZXJlZC5cbkF1dGhJbXBsLnByb3RvdHlwZS5zZXRQZXJzaXN0ZW5jZSA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHt9O1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIF9wZXJmb3JtQXBpUmVxdWVzdCxcbiAgRW5kcG9pbnQsXG4gIEh0dHBNZXRob2QsXG4gIFJlY2FwdGNoYUNsaWVudFR5cGUsXG4gIFJlY2FwdGNoYVZlcnNpb24sXG4gIF9hZGRUaWRJZk5lY2Vzc2FyeVxufSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBBdXRoIH0gZnJvbSAnLi4vLi4vbW9kZWwvcHVibGljX3R5cGVzJztcbmltcG9ydCB7IElkVG9rZW5SZXNwb25zZSB9IGZyb20gJy4uLy4uL21vZGVsL2lkX3Rva2VuJztcbmltcG9ydCB7IE1mYUVucm9sbG1lbnQgfSBmcm9tICcuLi9hY2NvdW50X21hbmFnZW1lbnQvbWZhJztcbmltcG9ydCB7IFNpZ25JbldpdGhJZHBSZXNwb25zZSB9IGZyb20gJy4vaWRwJztcbmltcG9ydCB7XG4gIFNpZ25JbldpdGhQaG9uZU51bWJlclJlcXVlc3QsXG4gIFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlXG59IGZyb20gJy4vc21zJztcblxuZXhwb3J0IGludGVyZmFjZSBGaW5hbGl6ZU1mYVJlc3BvbnNlIHtcbiAgaWRUb2tlbjogc3RyaW5nO1xuICByZWZyZXNoVG9rZW46IHN0cmluZztcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJZFRva2VuTWZhUmVzcG9uc2UgZXh0ZW5kcyBJZFRva2VuUmVzcG9uc2Uge1xuICBtZmFQZW5kaW5nQ3JlZGVudGlhbD86IHN0cmluZztcbiAgbWZhSW5mbz86IE1mYUVucm9sbG1lbnRbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdGFydFBob25lTWZhU2lnbkluUmVxdWVzdCB7XG4gIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmc7XG4gIG1mYUVucm9sbG1lbnRJZDogc3RyaW5nO1xuICBwaG9uZVNpZ25JbkluZm86IHtcbiAgICAvLyByZUNBUFRDSEEgdjIgdG9rZW5cbiAgICByZWNhcHRjaGFUb2tlbj86IHN0cmluZztcbiAgICAvLyByZUNBUFRDSEEgRW50ZXJwcmlzZSB0b2tlblxuICAgIGNhcHRjaGFSZXNwb25zZT86IHN0cmluZztcbiAgICBjbGllbnRUeXBlPzogUmVjYXB0Y2hhQ2xpZW50VHlwZTtcbiAgICByZWNhcHRjaGFWZXJzaW9uPzogUmVjYXB0Y2hhVmVyc2lvbjtcbiAgfTtcbiAgdGVuYW50SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhcnRQaG9uZU1mYVNpZ25JblJlc3BvbnNlIHtcbiAgcGhvbmVSZXNwb25zZUluZm86IHtcbiAgICBzZXNzaW9uSW5mbzogc3RyaW5nO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RhcnRTaWduSW5QaG9uZU1mYShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8U3RhcnRQaG9uZU1mYVNpZ25JblJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgU3RhcnRQaG9uZU1mYVNpZ25JblJlcXVlc3QsXG4gICAgU3RhcnRQaG9uZU1mYVNpZ25JblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuU1RBUlRfTUZBX1NJR05fSU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlcXVlc3Qge1xuICBtZmFQZW5kaW5nQ3JlZGVudGlhbDogc3RyaW5nO1xuICBwaG9uZVZlcmlmaWNhdGlvbkluZm86IFNpZ25JbldpdGhQaG9uZU51bWJlclJlcXVlc3Q7XG4gIHRlbmFudElkPzogc3RyaW5nO1xufVxuXG4vLyBUT1RQIE1GQSBTaWduIGluIG9ubHkgaGFzIGEgZmluYWxpemUgcGhhc2UuIFBob25lIE1GQSBoYXMgYSBzdGFydCBwaGFzZSB0byBpbml0aWF0ZSBzZW5kaW5nIGFuXG4vLyBTTVMgYW5kIGEgZmluYWxpemUgcGhhc2UgdG8gY29tcGxldGUgc2lnbiBpbi4gV2l0aCBUT1RQLCB0aGUgdXNlciBhbHJlYWR5IGhhcyB0aGUgT1RQIGluIHRoZVxuLy8gVE9UUC9BdXRoZW50aWNhdG9yIGFwcC5cbmV4cG9ydCBpbnRlcmZhY2UgRmluYWxpemVUb3RwTWZhU2lnbkluUmVxdWVzdCB7XG4gIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmc7XG4gIHRvdHBWZXJpZmljYXRpb25JbmZvOiB7IHZlcmlmaWNhdGlvbkNvZGU6IHN0cmluZyB9O1xuICB0ZW5hbnRJZD86IHN0cmluZztcbiAgbWZhRW5yb2xsbWVudElkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlc3BvbnNlIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIEZpbmFsaXplVG90cE1mYVNpZ25JblJlc3BvbnNlIGV4dGVuZHMgRmluYWxpemVNZmFSZXNwb25zZSB7fVxuXG5leHBvcnQgZnVuY3Rpb24gZmluYWxpemVTaWduSW5QaG9uZU1mYShcbiAgYXV0aDogQXV0aCxcbiAgcmVxdWVzdDogRmluYWxpemVQaG9uZU1mYVNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8RmluYWxpemVQaG9uZU1mYVNpZ25JblJlc3BvbnNlPiB7XG4gIHJldHVybiBfcGVyZm9ybUFwaVJlcXVlc3Q8XG4gICAgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlcXVlc3QsXG4gICAgRmluYWxpemVQaG9uZU1mYVNpZ25JblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuRklOQUxJWkVfTUZBX1NJR05fSU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5hbGl6ZVNpZ25JblRvdHBNZmEoXG4gIGF1dGg6IEF1dGgsXG4gIHJlcXVlc3Q6IEZpbmFsaXplVG90cE1mYVNpZ25JblJlcXVlc3Rcbik6IFByb21pc2U8RmluYWxpemVUb3RwTWZhU2lnbkluUmVzcG9uc2U+IHtcbiAgcmV0dXJuIF9wZXJmb3JtQXBpUmVxdWVzdDxcbiAgICBGaW5hbGl6ZVRvdHBNZmFTaWduSW5SZXF1ZXN0LFxuICAgIEZpbmFsaXplVG90cE1mYVNpZ25JblJlc3BvbnNlXG4gID4oXG4gICAgYXV0aCxcbiAgICBIdHRwTWV0aG9kLlBPU1QsXG4gICAgRW5kcG9pbnQuRklOQUxJWkVfTUZBX1NJR05fSU4sXG4gICAgX2FkZFRpZElmTmVjZXNzYXJ5KGF1dGgsIHJlcXVlc3QpXG4gICk7XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCB0eXBlIFBob25lT3JPYXV0aFRva2VuUmVzcG9uc2UgPVxuICB8IFNpZ25JbldpdGhQaG9uZU51bWJlclJlc3BvbnNlXG4gIHwgU2lnbkluV2l0aElkcFJlc3BvbnNlXG4gIHwgSWRUb2tlblJlc3BvbnNlO1xuIiwgIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIwIEdvb2dsZSBMTENcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5pbXBvcnQgeyBGYWN0b3JJZCwgTXVsdGlGYWN0b3JBc3NlcnRpb24gfSBmcm9tICcuLi9tb2RlbC9wdWJsaWNfdHlwZXMnO1xuaW1wb3J0IHsgZGVidWdGYWlsIH0gZnJvbSAnLi4vY29yZS91dGlsL2Fzc2VydCc7XG5pbXBvcnQgeyBNdWx0aUZhY3RvclNlc3Npb25JbXBsLCBNdWx0aUZhY3RvclNlc3Npb25UeXBlIH0gZnJvbSAnLi9tZmFfc2Vzc2lvbic7XG5pbXBvcnQgeyBGaW5hbGl6ZU1mYVJlc3BvbnNlIH0gZnJvbSAnLi4vYXBpL2F1dGhlbnRpY2F0aW9uL21mYSc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi9tb2RlbC9hdXRoJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbCBpbXBsZW1lbnRzIE11bHRpRmFjdG9yQXNzZXJ0aW9uIHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGZhY3RvcklkOiBGYWN0b3JJZCkge31cblxuICBfcHJvY2VzcyhcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgc2Vzc2lvbjogTXVsdGlGYWN0b3JTZXNzaW9uSW1wbCxcbiAgICBkaXNwbGF5TmFtZT86IHN0cmluZyB8IG51bGxcbiAgKTogUHJvbWlzZTxGaW5hbGl6ZU1mYVJlc3BvbnNlPiB7XG4gICAgc3dpdGNoIChzZXNzaW9uLnR5cGUpIHtcbiAgICAgIGNhc2UgTXVsdGlGYWN0b3JTZXNzaW9uVHlwZS5FTlJPTEw6XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5hbGl6ZUVucm9sbChhdXRoLCBzZXNzaW9uLmNyZWRlbnRpYWwsIGRpc3BsYXlOYW1lKTtcbiAgICAgIGNhc2UgTXVsdGlGYWN0b3JTZXNzaW9uVHlwZS5TSUdOX0lOOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluYWxpemVTaWduSW4oYXV0aCwgc2Vzc2lvbi5jcmVkZW50aWFsKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBkZWJ1Z0ZhaWwoJ3VuZXhwZWN0ZWQgTXVsdGlGYWN0b3JTZXNzaW9uVHlwZScpO1xuICAgIH1cbiAgfVxuXG4gIGFic3RyYWN0IF9maW5hbGl6ZUVucm9sbChcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgaWRUb2tlbjogc3RyaW5nLFxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbFxuICApOiBQcm9taXNlPEZpbmFsaXplTWZhUmVzcG9uc2U+O1xuICBhYnN0cmFjdCBfZmluYWxpemVTaWduSW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxGaW5hbGl6ZU1mYVJlc3BvbnNlPjtcbn1cbiIsICIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHtcbiAgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uLFxuICBNdWx0aUZhY3RvclNlc3Npb24sXG4gIEZhY3RvcklkXG59IGZyb20gJy4uLy4uL21vZGVsL3B1YmxpY190eXBlcyc7XG5pbXBvcnQgeyBBdXRoSW50ZXJuYWwgfSBmcm9tICcuLi8uLi9tb2RlbC9hdXRoJztcbmltcG9ydCB7XG4gIGZpbmFsaXplRW5yb2xsVG90cE1mYSxcbiAgc3RhcnRFbnJvbGxUb3RwTWZhLFxuICBTdGFydFRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2UsXG4gIFRvdHBWZXJpZmljYXRpb25JbmZvXG59IGZyb20gJy4uLy4uL2FwaS9hY2NvdW50X21hbmFnZW1lbnQvbWZhJztcbmltcG9ydCB7XG4gIEZpbmFsaXplTWZhUmVzcG9uc2UsXG4gIGZpbmFsaXplU2lnbkluVG90cE1mYVxufSBmcm9tICcuLi8uLi9hcGkvYXV0aGVudGljYXRpb24vbWZhJztcbmltcG9ydCB7IE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbCB9IGZyb20gJy4uLy4uL21mYS9tZmFfYXNzZXJ0aW9uJztcbmltcG9ydCB7IE11bHRpRmFjdG9yU2Vzc2lvbkltcGwgfSBmcm9tICcuLi9tZmFfc2Vzc2lvbic7XG5pbXBvcnQgeyBBdXRoRXJyb3JDb2RlIH0gZnJvbSAnLi4vLi4vY29yZS9lcnJvcnMnO1xuaW1wb3J0IHsgX2Fzc2VydCB9IGZyb20gJy4uLy4uL2NvcmUvdXRpbC9hc3NlcnQnO1xuXG4vKipcbiAqIFByb3ZpZGVyIGZvciBnZW5lcmF0aW5nIGEge0BsaW5rIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbn0uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgVG90cE11bHRpRmFjdG9yR2VuZXJhdG9yIHtcbiAgLyoqXG4gICAqIFByb3ZpZGVzIGEge0BsaW5rIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbn0gdG8gY29uZmlybSBvd25lcnNoaXAgb2ZcbiAgICogdGhlIFRPVFAgKHRpbWUtYmFzZWQgb25lLXRpbWUgcGFzc3dvcmQpIHNlY29uZCBmYWN0b3IuXG4gICAqIFRoaXMgYXNzZXJ0aW9uIGlzIHVzZWQgdG8gY29tcGxldGUgZW5yb2xsbWVudCBpbiBUT1RQIHNlY29uZCBmYWN0b3IuXG4gICAqXG4gICAqIEBwYXJhbSBzZWNyZXQgQSB7QGxpbmsgVG90cFNlY3JldH0gY29udGFpbmluZyB0aGUgc2hhcmVkIHNlY3JldCBrZXkgYW5kIG90aGVyIFRPVFAgcGFyYW1ldGVycy5cbiAgICogQHBhcmFtIG9uZVRpbWVQYXNzd29yZCBPbmUtdGltZSBwYXNzd29yZCBmcm9tIFRPVFAgQXBwLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb259IHdoaWNoIGNhbiBiZSB1c2VkIHdpdGhcbiAgICoge0BsaW5rIE11bHRpRmFjdG9yVXNlci5lbnJvbGx9LlxuICAgKi9cbiAgc3RhdGljIGFzc2VydGlvbkZvckVucm9sbG1lbnQoXG4gICAgc2VjcmV0OiBUb3RwU2VjcmV0LFxuICAgIG9uZVRpbWVQYXNzd29yZDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbiB7XG4gICAgcmV0dXJuIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwuX2Zyb21TZWNyZXQoc2VjcmV0LCBvbmVUaW1lUGFzc3dvcmQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3ZpZGVzIGEge0BsaW5rIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbn0gdG8gY29uZmlybSBvd25lcnNoaXAgb2YgdGhlIFRPVFAgc2Vjb25kIGZhY3Rvci5cbiAgICogVGhpcyBhc3NlcnRpb24gaXMgdXNlZCB0byBjb21wbGV0ZSBzaWduSW4gd2l0aCBUT1RQIGFzIHRoZSBzZWNvbmQgZmFjdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gZW5yb2xsbWVudElkIGlkZW50aWZpZXMgdGhlIGVucm9sbGVkIFRPVFAgc2Vjb25kIGZhY3Rvci5cbiAgICogQHBhcmFtIG9uZVRpbWVQYXNzd29yZCBPbmUtdGltZSBwYXNzd29yZCBmcm9tIFRPVFAgQXBwLlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb259IHdoaWNoIGNhbiBiZSB1c2VkIHdpdGhcbiAgICoge0BsaW5rIE11bHRpRmFjdG9yUmVzb2x2ZXIucmVzb2x2ZVNpZ25Jbn0uXG4gICAqL1xuICBzdGF0aWMgYXNzZXJ0aW9uRm9yU2lnbkluKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIG9uZVRpbWVQYXNzd29yZDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbiB7XG4gICAgcmV0dXJuIFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwuX2Zyb21FbnJvbGxtZW50SWQoXG4gICAgICBlbnJvbGxtZW50SWQsXG4gICAgICBvbmVUaW1lUGFzc3dvcmRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBwcm9taXNlIHRvIHtAbGluayBUb3RwU2VjcmV0fSB3aGljaCBjb250YWlucyB0aGUgVE9UUCBzaGFyZWQgc2VjcmV0IGtleSBhbmQgb3RoZXIgcGFyYW1ldGVycy5cbiAgICogQ3JlYXRlcyBhIFRPVFAgc2VjcmV0IGFzIHBhcnQgb2YgZW5yb2xsaW5nIGEgVE9UUCBzZWNvbmQgZmFjdG9yLlxuICAgKiBVc2VkIGZvciBnZW5lcmF0aW5nIGEgUVIgY29kZSBVUkwgb3IgaW5wdXR0aW5nIGludG8gYSBUT1RQIGFwcC5cbiAgICogVGhpcyBtZXRob2QgdXNlcyB0aGUgYXV0aCBpbnN0YW5jZSBjb3JyZXNwb25kaW5nIHRvIHRoZSB1c2VyIGluIHRoZSBtdWx0aUZhY3RvclNlc3Npb24uXG4gICAqXG4gICAqIEBwYXJhbSBzZXNzaW9uIFRoZSB7QGxpbmsgTXVsdGlGYWN0b3JTZXNzaW9ufSB0aGF0IHRoZSB1c2VyIGlzIHBhcnQgb2YuXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0byB7QGxpbmsgVG90cFNlY3JldH0uXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZ2VuZXJhdGVTZWNyZXQoXG4gICAgc2Vzc2lvbjogTXVsdGlGYWN0b3JTZXNzaW9uXG4gICk6IFByb21pc2U8VG90cFNlY3JldD4ge1xuICAgIGNvbnN0IG1mYVNlc3Npb24gPSBzZXNzaW9uIGFzIE11bHRpRmFjdG9yU2Vzc2lvbkltcGw7XG4gICAgX2Fzc2VydChcbiAgICAgIHR5cGVvZiBtZmFTZXNzaW9uLnVzZXI/LmF1dGggIT09ICd1bmRlZmluZWQnLFxuICAgICAgQXV0aEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUlxuICAgICk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzdGFydEVucm9sbFRvdHBNZmEobWZhU2Vzc2lvbi51c2VyLmF1dGgsIHtcbiAgICAgIGlkVG9rZW46IG1mYVNlc3Npb24uY3JlZGVudGlhbCxcbiAgICAgIHRvdHBFbnJvbGxtZW50SW5mbzoge31cbiAgICB9KTtcbiAgICByZXR1cm4gVG90cFNlY3JldC5fZnJvbVN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZShcbiAgICAgIHJlc3BvbnNlLFxuICAgICAgbWZhU2Vzc2lvbi51c2VyLmF1dGhcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpZGVudGlmaWVyIG9mIHRoZSBUT1RQIHNlY29uZCBmYWN0b3I6IGB0b3RwYC5cbiAgICovXG4gIHN0YXRpYyBGQUNUT1JfSUQ6ICd0b3RwJyA9IEZhY3RvcklkLlRPVFA7XG59XG5cbmV4cG9ydCBjbGFzcyBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsXG4gIGV4dGVuZHMgTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsXG4gIGltcGxlbWVudHMgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uXG57XG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IG90cDogc3RyaW5nLFxuICAgIHJlYWRvbmx5IGVucm9sbG1lbnRJZD86IHN0cmluZyxcbiAgICByZWFkb25seSBzZWNyZXQ/OiBUb3RwU2VjcmV0XG4gICkge1xuICAgIHN1cGVyKEZhY3RvcklkLlRPVFApO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX2Zyb21TZWNyZXQoXG4gICAgc2VjcmV0OiBUb3RwU2VjcmV0LFxuICAgIG90cDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwge1xuICAgIHJldHVybiBuZXcgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbChvdHAsIHVuZGVmaW5lZCwgc2VjcmV0KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc3RhdGljIF9mcm9tRW5yb2xsbWVudElkKFxuICAgIGVucm9sbG1lbnRJZDogc3RyaW5nLFxuICAgIG90cDogc3RyaW5nXG4gICk6IFRvdHBNdWx0aUZhY3RvckFzc2VydGlvbkltcGwge1xuICAgIHJldHVybiBuZXcgVG90cE11bHRpRmFjdG9yQXNzZXJ0aW9uSW1wbChvdHAsIGVucm9sbG1lbnRJZCk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIGFzeW5jIF9maW5hbGl6ZUVucm9sbChcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWwsXG4gICAgaWRUb2tlbjogc3RyaW5nLFxuICAgIGRpc3BsYXlOYW1lPzogc3RyaW5nIHwgbnVsbFxuICApOiBQcm9taXNlPEZpbmFsaXplTWZhUmVzcG9uc2U+IHtcbiAgICBfYXNzZXJ0KFxuICAgICAgdHlwZW9mIHRoaXMuc2VjcmV0ICE9PSAndW5kZWZpbmVkJyxcbiAgICAgIGF1dGgsXG4gICAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICAgKTtcbiAgICByZXR1cm4gZmluYWxpemVFbnJvbGxUb3RwTWZhKGF1dGgsIHtcbiAgICAgIGlkVG9rZW4sXG4gICAgICBkaXNwbGF5TmFtZSxcbiAgICAgIHRvdHBWZXJpZmljYXRpb25JbmZvOiB0aGlzLnNlY3JldC5fbWFrZVRvdHBWZXJpZmljYXRpb25JbmZvKHRoaXMub3RwKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBhc3luYyBfZmluYWxpemVTaWduSW4oXG4gICAgYXV0aDogQXV0aEludGVybmFsLFxuICAgIG1mYVBlbmRpbmdDcmVkZW50aWFsOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxGaW5hbGl6ZU1mYVJlc3BvbnNlPiB7XG4gICAgX2Fzc2VydChcbiAgICAgIHRoaXMuZW5yb2xsbWVudElkICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vdHAgIT09IHVuZGVmaW5lZCxcbiAgICAgIGF1dGgsXG4gICAgICBBdXRoRXJyb3JDb2RlLkFSR1VNRU5UX0VSUk9SXG4gICAgKTtcbiAgICBjb25zdCB0b3RwVmVyaWZpY2F0aW9uSW5mbyA9IHsgdmVyaWZpY2F0aW9uQ29kZTogdGhpcy5vdHAgfTtcbiAgICByZXR1cm4gZmluYWxpemVTaWduSW5Ub3RwTWZhKGF1dGgsIHtcbiAgICAgIG1mYVBlbmRpbmdDcmVkZW50aWFsLFxuICAgICAgbWZhRW5yb2xsbWVudElkOiB0aGlzLmVucm9sbG1lbnRJZCxcbiAgICAgIHRvdHBWZXJpZmljYXRpb25JbmZvXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBQcm92aWRlciBmb3IgZ2VuZXJhdGluZyBhIHtAbGluayBUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb259LlxuICpcbiAqIFN0b3JlcyB0aGUgc2hhcmVkIHNlY3JldCBrZXkgYW5kIG90aGVyIHBhcmFtZXRlcnMgdG8gZ2VuZXJhdGUgdGltZS1iYXNlZCBPVFBzLlxuICogSW1wbGVtZW50cyBtZXRob2RzIHRvIHJldHJpZXZlIHRoZSBzaGFyZWQgc2VjcmV0IGtleSBhbmQgZ2VuZXJhdGUgYSBRUiBjb2RlIFVSTC5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFRvdHBTZWNyZXQge1xuICAvKipcbiAgICogU2hhcmVkIHNlY3JldCBrZXkvc2VlZCB1c2VkIGZvciBlbnJvbGxpbmcgaW4gVE9UUCBNRkEgYW5kIGdlbmVyYXRpbmcgT1RQcy5cbiAgICovXG4gIHJlYWRvbmx5IHNlY3JldEtleTogc3RyaW5nO1xuICAvKipcbiAgICogSGFzaGluZyBhbGdvcml0aG0gdXNlZC5cbiAgICovXG4gIHJlYWRvbmx5IGhhc2hpbmdBbGdvcml0aG06IHN0cmluZztcbiAgLyoqXG4gICAqIExlbmd0aCBvZiB0aGUgb25lLXRpbWUgcGFzc3dvcmRzIHRvIGJlIGdlbmVyYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGNvZGVMZW5ndGg6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBpbnRlcnZhbCAoaW4gc2Vjb25kcykgd2hlbiB0aGUgT1RQIGNvZGVzIHNob3VsZCBjaGFuZ2UuXG4gICAqL1xuICByZWFkb25seSBjb2RlSW50ZXJ2YWxTZWNvbmRzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgdGltZXN0YW1wIChVVEMgc3RyaW5nKSBieSB3aGljaCBUT1RQIGVucm9sbG1lbnQgc2hvdWxkIGJlIGNvbXBsZXRlZC5cbiAgICovXG4gIC8vIFRoaXMgY2FuIGJlIHVzZWQgYnkgY2FsbGVycyB0byBzaG93IGEgY291bnRkb3duIG9mIHdoZW4gdG8gZW50ZXIgT1RQIGNvZGUgYnkuXG4gIHJlYWRvbmx5IGVucm9sbG1lbnRDb21wbGV0aW9uRGVhZGxpbmU6IHN0cmluZztcblxuICAvLyBUaGUgcHVibGljIG1lbWJlcnMgYXJlIGRlY2xhcmVkIG91dHNpZGUgdGhlIGNvbnN0cnVjdG9yIHNvIHRoZSBkb2NzIGNhbiBiZSBnZW5lcmF0ZWQuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgc2VjcmV0S2V5OiBzdHJpbmcsXG4gICAgaGFzaGluZ0FsZ29yaXRobTogc3RyaW5nLFxuICAgIGNvZGVMZW5ndGg6IG51bWJlcixcbiAgICBjb2RlSW50ZXJ2YWxTZWNvbmRzOiBudW1iZXIsXG4gICAgZW5yb2xsbWVudENvbXBsZXRpb25EZWFkbGluZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2Vzc2lvbkluZm86IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGF1dGg6IEF1dGhJbnRlcm5hbFxuICApIHtcbiAgICB0aGlzLnNlY3JldEtleSA9IHNlY3JldEtleTtcbiAgICB0aGlzLmhhc2hpbmdBbGdvcml0aG0gPSBoYXNoaW5nQWxnb3JpdGhtO1xuICAgIHRoaXMuY29kZUxlbmd0aCA9IGNvZGVMZW5ndGg7XG4gICAgdGhpcy5jb2RlSW50ZXJ2YWxTZWNvbmRzID0gY29kZUludGVydmFsU2Vjb25kcztcbiAgICB0aGlzLmVucm9sbG1lbnRDb21wbGV0aW9uRGVhZGxpbmUgPSBlbnJvbGxtZW50Q29tcGxldGlvbkRlYWRsaW5lO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBzdGF0aWMgX2Zyb21TdGFydFRvdHBNZmFFbnJvbGxtZW50UmVzcG9uc2UoXG4gICAgcmVzcG9uc2U6IFN0YXJ0VG90cE1mYUVucm9sbG1lbnRSZXNwb25zZSxcbiAgICBhdXRoOiBBdXRoSW50ZXJuYWxcbiAgKTogVG90cFNlY3JldCB7XG4gICAgcmV0dXJuIG5ldyBUb3RwU2VjcmV0KFxuICAgICAgcmVzcG9uc2UudG90cFNlc3Npb25JbmZvLnNoYXJlZFNlY3JldEtleSxcbiAgICAgIHJlc3BvbnNlLnRvdHBTZXNzaW9uSW5mby5oYXNoaW5nQWxnb3JpdGhtLFxuICAgICAgcmVzcG9uc2UudG90cFNlc3Npb25JbmZvLnZlcmlmaWNhdGlvbkNvZGVMZW5ndGgsXG4gICAgICByZXNwb25zZS50b3RwU2Vzc2lvbkluZm8ucGVyaW9kU2VjLFxuICAgICAgbmV3IERhdGUocmVzcG9uc2UudG90cFNlc3Npb25JbmZvLmZpbmFsaXplRW5yb2xsbWVudFRpbWUpLnRvVVRDU3RyaW5nKCksXG4gICAgICByZXNwb25zZS50b3RwU2Vzc2lvbkluZm8uc2Vzc2lvbkluZm8sXG4gICAgICBhdXRoXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX21ha2VUb3RwVmVyaWZpY2F0aW9uSW5mbyhvdHA6IHN0cmluZyk6IFRvdHBWZXJpZmljYXRpb25JbmZvIHtcbiAgICByZXR1cm4geyBzZXNzaW9uSW5mbzogdGhpcy5zZXNzaW9uSW5mbywgdmVyaWZpY2F0aW9uQ29kZTogb3RwIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIFFSIGNvZGUgVVJMIGFzIGRlc2NyaWJlZCBpblxuICAgKiBodHRwczovL2dpdGh1Yi5jb20vZ29vZ2xlL2dvb2dsZS1hdXRoZW50aWNhdG9yL3dpa2kvS2V5LVVyaS1Gb3JtYXRcbiAgICogVGhpcyBjYW4gYmUgZGlzcGxheWVkIHRvIHRoZSB1c2VyIGFzIGEgUVIgY29kZSB0byBiZSBzY2FubmVkIGludG8gYSBUT1RQIGFwcCBsaWtlIEdvb2dsZSBBdXRoZW50aWNhdG9yLlxuICAgKiBJZiB0aGUgb3B0aW9uYWwgcGFyYW1ldGVycyBhcmUgdW5zcGVjaWZpZWQsIGFuIGFjY291bnROYW1lIG9mIDx1c2VyRW1haWw+IGFuZCBpc3N1ZXIgb2YgPGZpcmViYXNlQXBwTmFtZT4gYXJlIHVzZWQuXG4gICAqXG4gICAqIEBwYXJhbSBhY2NvdW50TmFtZSB0aGUgbmFtZSBvZiB0aGUgYWNjb3VudC9hcHAgYWxvbmcgd2l0aCBhIHVzZXIgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIGlzc3VlciBpc3N1ZXIgb2YgdGhlIFRPVFAgKGxpa2VseSB0aGUgYXBwIG5hbWUpLlxuICAgKiBAcmV0dXJucyBBIFFSIGNvZGUgVVJMIHN0cmluZy5cbiAgICovXG4gIGdlbmVyYXRlUXJDb2RlVXJsKGFjY291bnROYW1lPzogc3RyaW5nLCBpc3N1ZXI/OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGxldCB1c2VEZWZhdWx0cyA9IGZhbHNlO1xuICAgIGlmIChfaXNFbXB0eVN0cmluZyhhY2NvdW50TmFtZSkgfHwgX2lzRW1wdHlTdHJpbmcoaXNzdWVyKSkge1xuICAgICAgdXNlRGVmYXVsdHMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAodXNlRGVmYXVsdHMpIHtcbiAgICAgIGlmIChfaXNFbXB0eVN0cmluZyhhY2NvdW50TmFtZSkpIHtcbiAgICAgICAgYWNjb3VudE5hbWUgPSB0aGlzLmF1dGguY3VycmVudFVzZXI/LmVtYWlsIHx8ICd1bmtub3dudXNlcic7XG4gICAgICB9XG4gICAgICBpZiAoX2lzRW1wdHlTdHJpbmcoaXNzdWVyKSkge1xuICAgICAgICBpc3N1ZXIgPSB0aGlzLmF1dGgubmFtZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGBvdHBhdXRoOi8vdG90cC8ke2lzc3Vlcn06JHthY2NvdW50TmFtZX0/c2VjcmV0PSR7dGhpcy5zZWNyZXRLZXl9Jmlzc3Vlcj0ke2lzc3Vlcn0mYWxnb3JpdGhtPSR7dGhpcy5oYXNoaW5nQWxnb3JpdGhtfSZkaWdpdHM9JHt0aGlzLmNvZGVMZW5ndGh9YDtcbiAgfVxufVxuXG4vKiogQGludGVybmFsICovXG5mdW5jdGlvbiBfaXNFbXB0eVN0cmluZyhpbnB1dD86IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIGlucHV0ID09PSAndW5kZWZpbmVkJyB8fCBpbnB1dD8ubGVuZ3RoID09PSAwO1xufVxuIiwgIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIHRvdHAgPSByZXF1aXJlKCcuL3RvdHAtNTBkNWQ1ZGQuanMnKTtcbnJlcXVpcmUoJ0BmaXJlYmFzZS9hcHAnKTtcbnJlcXVpcmUoJ0BmaXJlYmFzZS91dGlsJyk7XG5yZXF1aXJlKCdAZmlyZWJhc2UvY29tcG9uZW50Jyk7XG5yZXF1aXJlKCdAZmlyZWJhc2UvbG9nZ2VyJyk7XG5cblxuXG5leHBvcnRzLkFjdGlvbkNvZGVPcGVyYXRpb24gPSB0b3RwLkFjdGlvbkNvZGVPcGVyYXRpb247XG5leHBvcnRzLkFjdGlvbkNvZGVVUkwgPSB0b3RwLkFjdGlvbkNvZGVVUkw7XG5leHBvcnRzLkF1dGhDcmVkZW50aWFsID0gdG90cC5BdXRoQ3JlZGVudGlhbDtcbmV4cG9ydHMuQXV0aEVycm9yQ29kZXMgPSB0b3RwLkFVVEhfRVJST1JfQ09ERVNfTUFQX0RPX05PVF9VU0VfSU5URVJOQUxMWTtcbmV4cG9ydHMuRW1haWxBdXRoQ3JlZGVudGlhbCA9IHRvdHAuRW1haWxBdXRoQ3JlZGVudGlhbDtcbmV4cG9ydHMuRW1haWxBdXRoUHJvdmlkZXIgPSB0b3RwLkVtYWlsQXV0aFByb3ZpZGVyO1xuZXhwb3J0cy5GYWNlYm9va0F1dGhQcm92aWRlciA9IHRvdHAuRmFjZWJvb2tBdXRoUHJvdmlkZXI7XG5leHBvcnRzLkZhY3RvcklkID0gdG90cC5GYWN0b3JJZDtcbmV4cG9ydHMuR2l0aHViQXV0aFByb3ZpZGVyID0gdG90cC5HaXRodWJBdXRoUHJvdmlkZXI7XG5leHBvcnRzLkdvb2dsZUF1dGhQcm92aWRlciA9IHRvdHAuR29vZ2xlQXV0aFByb3ZpZGVyO1xuZXhwb3J0cy5PQXV0aENyZWRlbnRpYWwgPSB0b3RwLk9BdXRoQ3JlZGVudGlhbDtcbmV4cG9ydHMuT0F1dGhQcm92aWRlciA9IHRvdHAuT0F1dGhQcm92aWRlcjtcbmV4cG9ydHMuT3BlcmF0aW9uVHlwZSA9IHRvdHAuT3BlcmF0aW9uVHlwZTtcbmV4cG9ydHMuUGhvbmVBdXRoQ3JlZGVudGlhbCA9IHRvdHAuUGhvbmVBdXRoQ3JlZGVudGlhbDtcbmV4cG9ydHMuUGhvbmVBdXRoUHJvdmlkZXIgPSB0b3RwLlBob25lQXV0aFByb3ZpZGVyO1xuZXhwb3J0cy5QaG9uZU11bHRpRmFjdG9yR2VuZXJhdG9yID0gdG90cC5QaG9uZU11bHRpRmFjdG9yR2VuZXJhdG9yO1xuZXhwb3J0cy5Qcm92aWRlcklkID0gdG90cC5Qcm92aWRlcklkO1xuZXhwb3J0cy5SZWNhcHRjaGFWZXJpZmllciA9IHRvdHAuUmVjYXB0Y2hhVmVyaWZpZXI7XG5leHBvcnRzLlNBTUxBdXRoUHJvdmlkZXIgPSB0b3RwLlNBTUxBdXRoUHJvdmlkZXI7XG5leHBvcnRzLlNpZ25Jbk1ldGhvZCA9IHRvdHAuU2lnbkluTWV0aG9kO1xuZXhwb3J0cy5Ub3RwTXVsdGlGYWN0b3JHZW5lcmF0b3IgPSB0b3RwLlRvdHBNdWx0aUZhY3RvckdlbmVyYXRvcjtcbmV4cG9ydHMuVG90cFNlY3JldCA9IHRvdHAuVG90cFNlY3JldDtcbmV4cG9ydHMuVHdpdHRlckF1dGhQcm92aWRlciA9IHRvdHAuVHdpdHRlckF1dGhQcm92aWRlcjtcbmV4cG9ydHMuYXBwbHlBY3Rpb25Db2RlID0gdG90cC5hcHBseUFjdGlvbkNvZGU7XG5leHBvcnRzLmJlZm9yZUF1dGhTdGF0ZUNoYW5nZWQgPSB0b3RwLmJlZm9yZUF1dGhTdGF0ZUNoYW5nZWQ7XG5leHBvcnRzLmJyb3dzZXJDb29raWVQZXJzaXN0ZW5jZSA9IHRvdHAuYnJvd3NlckNvb2tpZVBlcnNpc3RlbmNlO1xuZXhwb3J0cy5icm93c2VyTG9jYWxQZXJzaXN0ZW5jZSA9IHRvdHAuYnJvd3NlckxvY2FsUGVyc2lzdGVuY2U7XG5leHBvcnRzLmJyb3dzZXJQb3B1cFJlZGlyZWN0UmVzb2x2ZXIgPSB0b3RwLmJyb3dzZXJQb3B1cFJlZGlyZWN0UmVzb2x2ZXI7XG5leHBvcnRzLmJyb3dzZXJTZXNzaW9uUGVyc2lzdGVuY2UgPSB0b3RwLmJyb3dzZXJTZXNzaW9uUGVyc2lzdGVuY2U7XG5leHBvcnRzLmNoZWNrQWN0aW9uQ29kZSA9IHRvdHAuY2hlY2tBY3Rpb25Db2RlO1xuZXhwb3J0cy5jb25maXJtUGFzc3dvcmRSZXNldCA9IHRvdHAuY29uZmlybVBhc3N3b3JkUmVzZXQ7XG5leHBvcnRzLmNvbm5lY3RBdXRoRW11bGF0b3IgPSB0b3RwLmNvbm5lY3RBdXRoRW11bGF0b3I7XG5leHBvcnRzLmNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZCA9IHRvdHAuY3JlYXRlVXNlcldpdGhFbWFpbEFuZFBhc3N3b3JkO1xuZXhwb3J0cy5kZWJ1Z0Vycm9yTWFwID0gdG90cC5kZWJ1Z0Vycm9yTWFwO1xuZXhwb3J0cy5kZWxldGVVc2VyID0gdG90cC5kZWxldGVVc2VyO1xuZXhwb3J0cy5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbCA9IHRvdHAuZmV0Y2hTaWduSW5NZXRob2RzRm9yRW1haWw7XG5leHBvcnRzLmdldEFkZGl0aW9uYWxVc2VySW5mbyA9IHRvdHAuZ2V0QWRkaXRpb25hbFVzZXJJbmZvO1xuZXhwb3J0cy5nZXRBdXRoID0gdG90cC5nZXRBdXRoO1xuZXhwb3J0cy5nZXRJZFRva2VuID0gdG90cC5nZXRJZFRva2VuO1xuZXhwb3J0cy5nZXRJZFRva2VuUmVzdWx0ID0gdG90cC5nZXRJZFRva2VuUmVzdWx0O1xuZXhwb3J0cy5nZXRNdWx0aUZhY3RvclJlc29sdmVyID0gdG90cC5nZXRNdWx0aUZhY3RvclJlc29sdmVyO1xuZXhwb3J0cy5nZXRSZWRpcmVjdFJlc3VsdCA9IHRvdHAuZ2V0UmVkaXJlY3RSZXN1bHQ7XG5leHBvcnRzLmluTWVtb3J5UGVyc2lzdGVuY2UgPSB0b3RwLmluTWVtb3J5UGVyc2lzdGVuY2U7XG5leHBvcnRzLmluZGV4ZWREQkxvY2FsUGVyc2lzdGVuY2UgPSB0b3RwLmluZGV4ZWREQkxvY2FsUGVyc2lzdGVuY2U7XG5leHBvcnRzLmluaXRpYWxpemVBdXRoID0gdG90cC5pbml0aWFsaXplQXV0aDtcbmV4cG9ydHMuaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZyA9IHRvdHAuaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZztcbmV4cG9ydHMuaXNTaWduSW5XaXRoRW1haWxMaW5rID0gdG90cC5pc1NpZ25JbldpdGhFbWFpbExpbms7XG5leHBvcnRzLmxpbmtXaXRoQ3JlZGVudGlhbCA9IHRvdHAubGlua1dpdGhDcmVkZW50aWFsO1xuZXhwb3J0cy5saW5rV2l0aFBob25lTnVtYmVyID0gdG90cC5saW5rV2l0aFBob25lTnVtYmVyO1xuZXhwb3J0cy5saW5rV2l0aFBvcHVwID0gdG90cC5saW5rV2l0aFBvcHVwO1xuZXhwb3J0cy5saW5rV2l0aFJlZGlyZWN0ID0gdG90cC5saW5rV2l0aFJlZGlyZWN0O1xuZXhwb3J0cy5tdWx0aUZhY3RvciA9IHRvdHAubXVsdGlGYWN0b3I7XG5leHBvcnRzLm9uQXV0aFN0YXRlQ2hhbmdlZCA9IHRvdHAub25BdXRoU3RhdGVDaGFuZ2VkO1xuZXhwb3J0cy5vbklkVG9rZW5DaGFuZ2VkID0gdG90cC5vbklkVG9rZW5DaGFuZ2VkO1xuZXhwb3J0cy5wYXJzZUFjdGlvbkNvZGVVUkwgPSB0b3RwLnBhcnNlQWN0aW9uQ29kZVVSTDtcbmV4cG9ydHMucHJvZEVycm9yTWFwID0gdG90cC5wcm9kRXJyb3JNYXA7XG5leHBvcnRzLnJlYXV0aGVudGljYXRlV2l0aENyZWRlbnRpYWwgPSB0b3RwLnJlYXV0aGVudGljYXRlV2l0aENyZWRlbnRpYWw7XG5leHBvcnRzLnJlYXV0aGVudGljYXRlV2l0aFBob25lTnVtYmVyID0gdG90cC5yZWF1dGhlbnRpY2F0ZVdpdGhQaG9uZU51bWJlcjtcbmV4cG9ydHMucmVhdXRoZW50aWNhdGVXaXRoUG9wdXAgPSB0b3RwLnJlYXV0aGVudGljYXRlV2l0aFBvcHVwO1xuZXhwb3J0cy5yZWF1dGhlbnRpY2F0ZVdpdGhSZWRpcmVjdCA9IHRvdHAucmVhdXRoZW50aWNhdGVXaXRoUmVkaXJlY3Q7XG5leHBvcnRzLnJlbG9hZCA9IHRvdHAucmVsb2FkO1xuZXhwb3J0cy5yZXZva2VBY2Nlc3NUb2tlbiA9IHRvdHAucmV2b2tlQWNjZXNzVG9rZW47XG5leHBvcnRzLnNlbmRFbWFpbFZlcmlmaWNhdGlvbiA9IHRvdHAuc2VuZEVtYWlsVmVyaWZpY2F0aW9uO1xuZXhwb3J0cy5zZW5kUGFzc3dvcmRSZXNldEVtYWlsID0gdG90cC5zZW5kUGFzc3dvcmRSZXNldEVtYWlsO1xuZXhwb3J0cy5zZW5kU2lnbkluTGlua1RvRW1haWwgPSB0b3RwLnNlbmRTaWduSW5MaW5rVG9FbWFpbDtcbmV4cG9ydHMuc2V0UGVyc2lzdGVuY2UgPSB0b3RwLnNldFBlcnNpc3RlbmNlO1xuZXhwb3J0cy5zaWduSW5Bbm9ueW1vdXNseSA9IHRvdHAuc2lnbkluQW5vbnltb3VzbHk7XG5leHBvcnRzLnNpZ25JbldpdGhDcmVkZW50aWFsID0gdG90cC5zaWduSW5XaXRoQ3JlZGVudGlhbDtcbmV4cG9ydHMuc2lnbkluV2l0aEN1c3RvbVRva2VuID0gdG90cC5zaWduSW5XaXRoQ3VzdG9tVG9rZW47XG5leHBvcnRzLnNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkID0gdG90cC5zaWduSW5XaXRoRW1haWxBbmRQYXNzd29yZDtcbmV4cG9ydHMuc2lnbkluV2l0aEVtYWlsTGluayA9IHRvdHAuc2lnbkluV2l0aEVtYWlsTGluaztcbmV4cG9ydHMuc2lnbkluV2l0aFBob25lTnVtYmVyID0gdG90cC5zaWduSW5XaXRoUGhvbmVOdW1iZXI7XG5leHBvcnRzLnNpZ25JbldpdGhQb3B1cCA9IHRvdHAuc2lnbkluV2l0aFBvcHVwO1xuZXhwb3J0cy5zaWduSW5XaXRoUmVkaXJlY3QgPSB0b3RwLnNpZ25JbldpdGhSZWRpcmVjdDtcbmV4cG9ydHMuc2lnbk91dCA9IHRvdHAuc2lnbk91dDtcbmV4cG9ydHMudW5saW5rID0gdG90cC51bmxpbms7XG5leHBvcnRzLnVwZGF0ZUN1cnJlbnRVc2VyID0gdG90cC51cGRhdGVDdXJyZW50VXNlcjtcbmV4cG9ydHMudXBkYXRlRW1haWwgPSB0b3RwLnVwZGF0ZUVtYWlsO1xuZXhwb3J0cy51cGRhdGVQYXNzd29yZCA9IHRvdHAudXBkYXRlUGFzc3dvcmQ7XG5leHBvcnRzLnVwZGF0ZVBob25lTnVtYmVyID0gdG90cC51cGRhdGVQaG9uZU51bWJlcjtcbmV4cG9ydHMudXBkYXRlUHJvZmlsZSA9IHRvdHAudXBkYXRlUHJvZmlsZTtcbmV4cG9ydHMudXNlRGV2aWNlTGFuZ3VhZ2UgPSB0b3RwLnVzZURldmljZUxhbmd1YWdlO1xuZXhwb3J0cy52YWxpZGF0ZVBhc3N3b3JkID0gdG90cC52YWxpZGF0ZVBhc3N3b3JkO1xuZXhwb3J0cy52ZXJpZnlCZWZvcmVVcGRhdGVFbWFpbCA9IHRvdHAudmVyaWZ5QmVmb3JlVXBkYXRlRW1haWw7XG5leHBvcnRzLnZlcmlmeVBhc3N3b3JkUmVzZXRDb2RlID0gdG90cC52ZXJpZnlQYXNzd29yZFJlc2V0Q29kZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcFxuIiwgIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIGF1dGggPSByZXF1aXJlKCdAZmlyZWJhc2UvYXV0aCcpO1xuXG5cblxuT2JqZWN0LmtleXMoYXV0aCkuZm9yRWFjaChmdW5jdGlvbiAoaykge1xuXHRpZiAoayAhPT0gJ2RlZmF1bHQnICYmICFleHBvcnRzLmhhc093blByb3BlcnR5KGspKSBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgaywge1xuXHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0Z2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBhdXRoW2tdOyB9XG5cdH0pO1xufSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5janMuanMubWFwXG4iLCAiLyoqXG4gKiB1dXUuZ2wgTWFya2Rvd24gVXBsb2FkZXIgUGx1Z2luIGZvciBPYnNpZGlhblxuICpcbiAqIFVwbG9hZCB5b3VyIE9ic2lkaWFuIG5vdGVzIHRvIHV1dS5nbCBhcyBiZWF1dGlmdWxseSByZW5kZXJlZCBNYXJrZG93biBkb2N1bWVudHNcbiAqIHdpdGggYWxsIGltYWdlcyBhbmQgaW50ZXJuYWwgbGlua3MgcHJlc2VydmVkLlxuICovXG5cbmltcG9ydCB7IFBsdWdpbiwgVEZpbGUsIE5vdGljZSB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IEF1dGhNYW5hZ2VyIH0gZnJvbSAnLi9hdXRoLW1hbmFnZXInO1xuaW1wb3J0IHsgVXBsb2FkTW9kYWwgfSBmcm9tICcuL3VwbG9hZC1tb2RhbCc7XG5pbXBvcnQgeyBVdXVnbFNldHRpbmdUYWIsIFV1dWdsUGx1Z2luU2V0dGluZ3MsIERFRkFVTFRfU0VUVElOR1MgfSBmcm9tICcuL3NldHRpbmdzJztcbmltcG9ydCBGaW5nZXJwcmludEpTIGZyb20gJ0BmaW5nZXJwcmludGpzL2ZpbmdlcnByaW50anMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBVdXVnbFBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG4gIHNldHRpbmdzOiBVdXVnbFBsdWdpblNldHRpbmdzID0gREVGQVVMVF9TRVRUSU5HUztcbiAgYXV0aE1hbmFnZXI6IEF1dGhNYW5hZ2VyID0gbmV3IEF1dGhNYW5hZ2VyKCk7XG4gIGZpbmdlcnByaW50OiBzdHJpbmcgPSAnJztcbiAgc3RhdHVzQmFySXRlbTogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgLy8gTWVtb3J5LWJhc2VkIFVSTCBzdG9yYWdlIChmaWxlIHBhdGggLT4gdXV1LmdsIFVSTClcbiAgdXJsQ2FjaGU6IE1hcDxzdHJpbmcsIHN0cmluZz4gPSBuZXcgTWFwKCk7XG5cbiAgYXN5bmMgb25sb2FkKCkge1xuICAgIGNvbnNvbGUubG9nKCdcdTI3MDUgTG9hZGluZyB1dXUuZ2wgTWFya2Rvd24gVXBsb2FkZXIgcGx1Z2luJyk7XG5cbiAgICAvLyBMb2FkIHNldHRpbmdzXG4gICAgYXdhaXQgdGhpcy5sb2FkU2V0dGluZ3MoKTtcblxuICAgIC8vIFJlc3RvcmUgVVJMIGNhY2hlIGZyb20gc2V0dGluZ3MgKHBlcnNpc3RlbnQgc3RvcmFnZSlcbiAgICB0aGlzLnJlc3RvcmVVcmxDYWNoZUZyb21TZXR0aW5ncygpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBmaW5nZXJwcmludFxuICAgIGF3YWl0IHRoaXMuaW5pdGlhbGl6ZUZpbmdlcnByaW50KCk7XG5cbiAgICAvLyBBdXRvIHJlLWF1dGhlbnRpY2F0ZSBpbiBiYWNrZ3JvdW5kIChub24tYmxvY2tpbmcgZm9yIGZhc3Qgc3RhcnR1cClcbiAgICB0aGlzLmF1dG9SZWF1dGhlbnRpY2F0ZSgpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1x1Mjc0QyBCYWNrZ3JvdW5kIHJlLWF1dGhlbnRpY2F0aW9uIGZhaWxlZDonLCBlcnIpO1xuICAgIH0pO1xuXG4gICAgLy8gTW9uaXRvciBGaXJlYmFzZSBhdXRoIHN0YXRlIGNoYW5nZXNcbiAgICB0aGlzLm1vbml0b3JBdXRoU3RhdGUoKTtcblxuICAgIC8vIEFkZCBzZXR0aW5ncyB0YWJcbiAgICB0aGlzLmFkZFNldHRpbmdUYWIobmV3IFV1dWdsU2V0dGluZ1RhYih0aGlzLmFwcCwgdGhpcykpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBVUkwgY2FjaGUgZnJvbSBmcm9udG1hdHRlciAobm9uLWJsb2NraW5nKVxuICAgIHRoaXMuaW5pdGlhbGl6ZVVybENhY2hlKCkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgY29uc29sZS5lcnJvcignXHUyNzRDIEZhaWxlZCB0byBpbml0aWFsaXplIFVSTCBjYWNoZTonLCBlcnIpO1xuICAgIH0pO1xuXG4gICAgLy8gQWRkIHN0YXR1cyBiYXIgaXRlbVxuICAgIHRoaXMuc3RhdHVzQmFySXRlbSA9IHRoaXMuYWRkU3RhdHVzQmFySXRlbSgpO1xuICAgIHRoaXMuc3RhdHVzQmFySXRlbS5hZGRDbGFzcygndXV1Z2wtc3RhdHVzLWJhcicpO1xuICAgIC8vIE5vdGU6IHVwZGF0ZVN0YXR1c0JhcigpIGlzIGNhbGxlZCBhZnRlciBjYWNoZSBpbml0aWFsaXphdGlvbiBjb21wbGV0ZXNcblxuICAgIC8vIExpc3RlbiB0byBhY3RpdmUgZmlsZSBjaGFuZ2VzXG4gICAgdGhpcy5yZWdpc3RlckV2ZW50KFxuICAgICAgdGhpcy5hcHAud29ya3NwYWNlLm9uKCdhY3RpdmUtbGVhZi1jaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgIHRoaXMudXBkYXRlU3RhdHVzQmFyKCk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBMaXN0ZW4gdG8gZmlsZSBjaGFuZ2VzIChmb3IgZnJvbnRtYXR0ZXIgdXBkYXRlcylcbiAgICB0aGlzLnJlZ2lzdGVyRXZlbnQoXG4gICAgICB0aGlzLmFwcC52YXVsdC5vbignbW9kaWZ5JywgKGZpbGUpID0+IHtcbiAgICAgICAgY29uc3QgYWN0aXZlRmlsZSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XG4gICAgICAgIGlmIChmaWxlID09PSBhY3RpdmVGaWxlKSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVTdGF0dXNCYXIoKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gUmVnaXN0ZXIgb2JzaWRpYW46Ly8gVVJMIGhhbmRsZXIgZm9yIGF1dGggY2FsbGJhY2tzXG4gICAgdGhpcy5yZWdpc3Rlck9ic2lkaWFuUHJvdG9jb2xIYW5kbGVyKCd1dXVnbC11cGxvYWRlcicsIChwYXJhbXMpID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKCdcdUQ4M0RcdUREMTcgUmVjZWl2ZWQgb2JzaWRpYW46Ly8gVVJMOicsIHBhcmFtcyk7XG5cbiAgICAgIC8vIFJlY29uc3RydWN0IGZ1bGwgVVJJIGZvciBhdXRoIG1hbmFnZXJcbiAgICAgIGNvbnN0IHVyaSA9IGBvYnNpZGlhbjovL3V1dWdsLXVwbG9hZGVyJHtwYXJhbXMuYWN0aW9uID8gJy8nICsgcGFyYW1zLmFjdGlvbiA6ICcnfT8ke25ldyBVUkxTZWFyY2hQYXJhbXMocGFyYW1zKS50b1N0cmluZygpfWA7XG5cbiAgICAgIC8vIEhhbmRsZSBhdXRoIGNhbGxiYWNrXG4gICAgICBjb25zdCBoYW5kbGVkID0gdGhpcy5hdXRoTWFuYWdlci5oYW5kbGVDYWxsYmFjayh1cmkpO1xuICAgICAgaWYgKGhhbmRsZWQpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1x1MjcwNSBBdXRoIGNhbGxiYWNrIGhhbmRsZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgcmliYm9uIGljb25cbiAgICB0aGlzLmFkZFJpYmJvbkljb24oJ3VwbG9hZC1jbG91ZCcsICdVcGxvYWQgbm90ZSB0byB1dXUuZ2wnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLmhhbmRsZVVwbG9hZENvbW1hbmQoKTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBjb21tYW5kOiBVcGxvYWQgY3VycmVudCBub3RlXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAndXBsb2FkLW1hcmtkb3duJyxcbiAgICAgIG5hbWU6ICdVcGxvYWQgY3VycmVudCBub3RlIHRvIHV1dS5nbCcsXG4gICAgICBjaGVja0NhbGxiYWNrOiAoY2hlY2tpbmc6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgY29uc3QgYWN0aXZlRmlsZSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XG4gICAgICAgIGlmIChhY3RpdmVGaWxlKSB7XG4gICAgICAgICAgaWYgKCFjaGVja2luZykge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVVcGxvYWRDb21tYW5kKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgY29tbWFuZDogVXBsb2FkIHdpdGggY3VzdG9tIHNob3J0Y29kZVxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3VwbG9hZC1tYXJrZG93bi1jdXN0b20nLFxuICAgICAgbmFtZTogJ1VwbG9hZCBjdXJyZW50IG5vdGUgd2l0aCBjdXN0b20gc2hvcnRjb2RlJyxcbiAgICAgIGNoZWNrQ2FsbGJhY2s6IChjaGVja2luZzogYm9vbGVhbikgPT4ge1xuICAgICAgICBjb25zdCBhY3RpdmVGaWxlID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKTtcbiAgICAgICAgaWYgKGFjdGl2ZUZpbGUpIHtcbiAgICAgICAgICBpZiAoIWNoZWNraW5nKSB7XG4gICAgICAgICAgICB0aGlzLm9wZW5VcGxvYWRNb2RhbChhY3RpdmVGaWxlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIEFkZCBjb21tYW5kOiBDb3B5IHV1dS5nbCBsaW5rXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnY29weS11dXVnbC1saW5rJyxcbiAgICAgIG5hbWU6ICdDb3B5IHV1dS5nbCBsaW5rJyxcbiAgICAgIGNoZWNrQ2FsbGJhY2s6IChjaGVja2luZzogYm9vbGVhbikgPT4ge1xuICAgICAgICBjb25zdCBhY3RpdmVGaWxlID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKTtcbiAgICAgICAgaWYgKGFjdGl2ZUZpbGUpIHtcbiAgICAgICAgICBjb25zdCB1cmwgPSB0aGlzLmdldFV1dWdsTGlua0Zyb21GaWxlKGFjdGl2ZUZpbGUpO1xuICAgICAgICAgIGlmICh1cmwpIHtcbiAgICAgICAgICAgIGlmICghY2hlY2tpbmcpIHtcbiAgICAgICAgICAgICAgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodXJsKTtcbiAgICAgICAgICAgICAgbmV3IE5vdGljZSgnXHVEODNEXHVEQ0NFIHV1dS5nbCBsaW5rIGNvcGllZCB0byBjbGlwYm9hcmQhJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnNvbGUubG9nKCdcdTI3MDUgdXV1LmdsIHBsdWdpbiBsb2FkZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gIH1cblxuICBhc3luYyBvbnVubG9hZCgpIHtcbiAgICBjb25zb2xlLmxvZygnVW5sb2FkaW5nIHV1dS5nbCBwbHVnaW4nKTtcbiAgfVxuXG4gIGFzeW5jIGxvYWRTZXR0aW5ncygpIHtcbiAgICB0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKTtcbiAgfVxuXG4gIGFzeW5jIHNhdmVTZXR0aW5ncygpIHtcbiAgICBhd2FpdCB0aGlzLnNhdmVEYXRhKHRoaXMuc2V0dGluZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc3RvcmUgVVJMIGNhY2hlIGZyb20gcGVyc2lzdGVudCBzZXR0aW5ncyBzdG9yYWdlXG4gICAqL1xuICBwcml2YXRlIHJlc3RvcmVVcmxDYWNoZUZyb21TZXR0aW5ncygpIHtcbiAgICBpZiAodGhpcy5zZXR0aW5ncy51cmxDYWNoZSAmJiB0eXBlb2YgdGhpcy5zZXR0aW5ncy51cmxDYWNoZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIC8vIENvbnZlcnQgc2V0dGluZ3Mgb2JqZWN0IHRvIE1hcFxuICAgICAgZm9yIChjb25zdCBbZmlsZVBhdGgsIHVybF0gb2YgT2JqZWN0LmVudHJpZXModGhpcy5zZXR0aW5ncy51cmxDYWNoZSkpIHtcbiAgICAgICAgdGhpcy51cmxDYWNoZS5zZXQoZmlsZVBhdGgsIHVybCk7XG4gICAgICB9XG4gICAgICBjb25zb2xlLmxvZyhgXHUyNzA1IFJlc3RvcmVkICR7dGhpcy51cmxDYWNoZS5zaXplfSBVUkxzIGZyb20gcGVyc2lzdGVudCBzdG9yYWdlYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgVVJMIGNhY2hlIGJ5IHNjYW5uaW5nIGFsbCBtYXJrZG93biBmaWxlcyBmb3IgdXV1Z2wgZnJvbnRtYXR0ZXJcbiAgICogKExlZ2FjeSBzdXBwb3J0IC0gZm9yIGZyb250bWF0dGVyLWJhc2VkIHN0b3JhZ2UpXG4gICAqL1xuICBhc3luYyBpbml0aWFsaXplVXJsQ2FjaGUoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnNvbGUubG9nKCdcdUQ4M0RcdUREMDQgSW5pdGlhbGl6aW5nIFVSTCBjYWNoZSBmcm9tIGZyb250bWF0dGVyLi4uJyk7XG4gICAgICBjb25zdCBmaWxlcyA9IHRoaXMuYXBwLnZhdWx0LmdldE1hcmtkb3duRmlsZXMoKTtcbiAgICAgIGxldCBjYWNoZWRDb3VudCA9IDA7XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCB0aGlzLmFwcC52YXVsdC5yZWFkKGZpbGUpO1xuXG4gICAgICAgICAgLy8gUGFyc2UgZnJvbnRtYXR0ZXJcbiAgICAgICAgICBjb25zdCBmcm9udG1hdHRlclJlZ2V4ID0gL14tLS1cXG4oW1xcc1xcU10qPylcXG4tLS0vO1xuICAgICAgICAgIGNvbnN0IG1hdGNoID0gY29udGVudC5tYXRjaChmcm9udG1hdHRlclJlZ2V4KTtcblxuICAgICAgICAgIGlmICghbWF0Y2gpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgY29uc3QgZnJvbnRtYXR0ZXIgPSBtYXRjaFsxXTtcbiAgICAgICAgICBjb25zdCBsaW5lcyA9IGZyb250bWF0dGVyLnNwbGl0KCdcXG4nKTtcblxuICAgICAgICAgIC8vIEZpbmQgdXV1Z2wgZmllbGRcbiAgICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgICAgICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoJ3V1dWdsOicpKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHVybCA9IGxpbmUucmVwbGFjZSgndXV1Z2w6JywgJycpLnRyaW0oKTtcbiAgICAgICAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgICAgICAgIHRoaXMudXJsQ2FjaGUuc2V0KGZpbGUucGF0aCwgdXJsKTtcbiAgICAgICAgICAgICAgICBjYWNoZWRDb3VudCsrO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIC8vIFNraXAgZmlsZXMgdGhhdCBjYW4ndCBiZSByZWFkXG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coYFx1MjcwNSBVUkwgY2FjaGUgaW5pdGlhbGl6ZWQ6ICR7Y2FjaGVkQ291bnR9IGxpbmtzIGZvdW5kYCk7XG5cbiAgICAgIC8vIFVwZGF0ZSBzdGF0dXMgYmFyIGFmdGVyIGNhY2hlIGlzIHJlYWR5XG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZVN0YXR1c0JhcigpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcdTI3NEMgRmFpbGVkIHRvIGluaXRpYWxpemUgVVJMIGNhY2hlOicsIGVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBkZXZpY2UgZmluZ2VycHJpbnQgZm9yIHJhdGUgbGltaXRpbmdcbiAgICovXG4gIGFzeW5jIGluaXRpYWxpemVGaW5nZXJwcmludCgpIHtcbiAgICBpZiAodGhpcy5zZXR0aW5ncy5maW5nZXJwcmludCkge1xuICAgICAgdGhpcy5maW5nZXJwcmludCA9IHRoaXMuc2V0dGluZ3MuZmluZ2VycHJpbnQ7XG4gICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVERDExIExvYWRlZCBleGlzdGluZyBmaW5nZXJwcmludCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBmcCA9IGF3YWl0IEZpbmdlcnByaW50SlMubG9hZCgpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZnAuZ2V0KCk7XG4gICAgICB0aGlzLmZpbmdlcnByaW50ID0gcmVzdWx0LnZpc2l0b3JJZDtcbiAgICAgIHRoaXMuc2V0dGluZ3MuZmluZ2VycHJpbnQgPSB0aGlzLmZpbmdlcnByaW50O1xuICAgICAgYXdhaXQgdGhpcy5zYXZlU2V0dGluZ3MoKTtcbiAgICAgIGNvbnNvbGUubG9nKCdcdUQ4M0RcdUREMTEgRmluZ2VycHJpbnQgZ2VuZXJhdGVkOicsIHRoaXMuZmluZ2VycHJpbnQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcdTI3NEMgRmFpbGVkIHRvIGdlbmVyYXRlIGZpbmdlcnByaW50OicsIGVycm9yKTtcbiAgICAgIC8vIEZhbGxiYWNrIHRvIHRpbWVzdGFtcC1iYXNlZCBJRFxuICAgICAgdGhpcy5maW5nZXJwcmludCA9IGBvYnNpZGlhbi0ke0RhdGUubm93KCl9YDtcbiAgICAgIHRoaXMuc2V0dGluZ3MuZmluZ2VycHJpbnQgPSB0aGlzLmZpbmdlcnByaW50O1xuICAgICAgYXdhaXQgdGhpcy5zYXZlU2V0dGluZ3MoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXV0byByZS1hdXRoZW50aWNhdGUgdXNpbmcgc2F2ZWQgY3JlZGVudGlhbHNcbiAgICovXG4gIGFzeW5jIGF1dG9SZWF1dGhlbnRpY2F0ZSgpIHtcbiAgICAvLyBJZiBhbHJlYWR5IGF1dGhlbnRpY2F0ZWQsIHNraXBcbiAgICBpZiAodGhpcy5hdXRoTWFuYWdlci5pc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgY29uc29sZS5sb2coJ1x1MjcwNSBBbHJlYWR5IGF1dGhlbnRpY2F0ZWQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJZiB3ZSBoYXZlIHNhdmVkIGVtYWlsIGFuZCB1aWQsIHRyeSB0byByZS1hdXRoZW50aWNhdGVcbiAgICBpZiAodGhpcy5zZXR0aW5ncy5lbWFpbCAmJiB0aGlzLnNldHRpbmdzLnVpZCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc29sZS5sb2coJ1x1RDgzRFx1REQwNCBBdHRlbXB0aW5nIGF1dG8gcmUtYXV0aGVudGljYXRpb24gZm9yOicsIHRoaXMuc2V0dGluZ3MuZW1haWwpO1xuXG4gICAgICAgIC8vIENhbGwgRmlyZWJhc2UgRnVuY3Rpb24gdG8gZ2VuZXJhdGUgY3VzdG9tIHRva2VuXG4gICAgICAgIGNvbnN0IHsgZnVuY3Rpb25zIH0gPSBhd2FpdCBpbXBvcnQoJy4vZmlyZWJhc2UtY29uZmlnJyk7XG4gICAgICAgIGNvbnN0IHsgaHR0cHNDYWxsYWJsZSB9ID0gYXdhaXQgaW1wb3J0KCdmaXJlYmFzZS9mdW5jdGlvbnMnKTtcblxuICAgICAgICBjb25zdCBnZW5lcmF0ZUN1c3RvbVRva2VuID0gaHR0cHNDYWxsYWJsZShmdW5jdGlvbnMsICdnZW5lcmF0ZUN1c3RvbVRva2VuJyk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdlbmVyYXRlQ3VzdG9tVG9rZW4oeyBlbWFpbDogdGhpcy5zZXR0aW5ncy5lbWFpbCB9KTtcbiAgICAgICAgY29uc3QgeyBjdXN0b21Ub2tlbiB9ID0gcmVzdWx0LmRhdGEgYXMgYW55O1xuXG4gICAgICAgIC8vIFNpZ24gaW4gd2l0aCBjdXN0b20gdG9rZW5cbiAgICAgICAgY29uc3QgeyBhdXRoIH0gPSBhd2FpdCBpbXBvcnQoJy4vZmlyZWJhc2UtY29uZmlnJyk7XG4gICAgICAgIGNvbnN0IHsgc2lnbkluV2l0aEN1c3RvbVRva2VuIH0gPSBhd2FpdCBpbXBvcnQoJ2ZpcmViYXNlL2F1dGgnKTtcblxuICAgICAgICBhd2FpdCBzaWduSW5XaXRoQ3VzdG9tVG9rZW4oYXV0aCwgY3VzdG9tVG9rZW4pO1xuICAgICAgICBjb25zb2xlLmxvZygnXHUyNzA1IEF1dG8gcmUtYXV0aGVudGljYXRpb24gc3VjY2Vzc2Z1bCcpO1xuICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdcdTI3NEMgQXV0byByZS1hdXRoZW50aWNhdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgICAvLyBDbGVhciBpbnZhbGlkIGNyZWRlbnRpYWxzXG4gICAgICAgIHRoaXMuc2V0dGluZ3MuZW1haWwgPSAnJztcbiAgICAgICAgdGhpcy5zZXR0aW5ncy51aWQgPSAnJztcbiAgICAgICAgYXdhaXQgdGhpcy5zYXZlU2V0dGluZ3MoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHVwbG9hZCBjb21tYW5kXG4gICAqL1xuICBhc3luYyBoYW5kbGVVcGxvYWRDb21tYW5kKCkge1xuICAgIGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpO1xuXG4gICAgaWYgKCFhY3RpdmVGaWxlKSB7XG4gICAgICBuZXcgTm90aWNlKCdObyBhY3RpdmUgZmlsZSB0byB1cGxvYWQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBBdXRoZW50aWNhdGUgaWYgbmVlZGVkXG4gICAgdHJ5IHtcbiAgICAgIGlmICghdGhpcy5hdXRoTWFuYWdlci5pc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgICBuZXcgTm90aWNlKCdcdUQ4M0RcdUREMTAgU2lnbmluZyBpbiB3aXRoIEdvb2dsZS4uLicpO1xuICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5hdXRoTWFuYWdlci5zaWduSW5XaXRoR29vZ2xlKCk7XG5cbiAgICAgICAgLy8gU2F2ZSBlbWFpbCBhbmQgVUlEIHRvIHNldHRpbmdzIGZvciBhdXRvIHJlLWF1dGhlbnRpY2F0aW9uXG4gICAgICAgIGlmICh1c2VyLmVtYWlsICYmIHVzZXIudWlkKSB7XG4gICAgICAgICAgdGhpcy5zZXR0aW5ncy5lbWFpbCA9IHVzZXIuZW1haWw7XG4gICAgICAgICAgdGhpcy5zZXR0aW5ncy51aWQgPSB1c2VyLnVpZDtcbiAgICAgICAgICBhd2FpdCB0aGlzLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICB9XG5cbiAgICAgICAgbmV3IE5vdGljZShgXHUyNzA1IFdlbGNvbWUsICR7dXNlci5lbWFpbCB8fCAnVXNlcid9IWApO1xuICAgICAgfVxuXG4gICAgICAvLyBPcGVuIHVwbG9hZCBtb2RhbFxuICAgICAgdGhpcy5vcGVuVXBsb2FkTW9kYWwoYWN0aXZlRmlsZSk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcignXHUyNzRDIEF1dGhlbnRpY2F0aW9uIGZhaWxlZDonLCBlcnJvcik7XG4gICAgICBuZXcgTm90aWNlKGBcdTI3NEMgQXV0aGVudGljYXRpb24gZmFpbGVkOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vbml0b3IgRmlyZWJhc2UgYXV0aGVudGljYXRpb24gc3RhdGVcbiAgICovXG4gIHByaXZhdGUgbW9uaXRvckF1dGhTdGF0ZSgpIHtcbiAgICBjb25zdCB7IGF1dGggfSA9IHJlcXVpcmUoJy4vZmlyZWJhc2UtY29uZmlnJyk7XG4gICAgY29uc3QgeyBvbkF1dGhTdGF0ZUNoYW5nZWQgfSA9IHJlcXVpcmUoJ2ZpcmViYXNlL2F1dGgnKTtcblxuICAgIG9uQXV0aFN0YXRlQ2hhbmdlZChhdXRoLCAodXNlcjogYW55KSA9PiB7XG4gICAgICBpZiAodXNlcikge1xuICAgICAgICBjb25zb2xlLmxvZygnXHUyNzA1IFVzZXIgYXV0aGVudGljYXRlZDonLCB1c2VyLmVtYWlsKTtcblxuICAgICAgICAvLyBVcGRhdGUgZW1haWwgYW5kIFVJRCBpbiBzZXR0aW5nc1xuICAgICAgICBpZiAodXNlci5lbWFpbCAmJiB1c2VyLnVpZCkge1xuICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmVtYWlsICE9PSB1c2VyLmVtYWlsIHx8IHRoaXMuc2V0dGluZ3MudWlkICE9PSB1c2VyLnVpZCkge1xuICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5lbWFpbCA9IHVzZXIuZW1haWw7XG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLnVpZCA9IHVzZXIudWlkO1xuICAgICAgICAgICAgdGhpcy5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdcdTIxMzlcdUZFMEYgTm8gdXNlciBhdXRoZW50aWNhdGVkJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogT3BlbiB1cGxvYWQgbW9kYWxcbiAgICovXG4gIHByaXZhdGUgb3BlblVwbG9hZE1vZGFsKGZpbGU6IFRGaWxlKSB7XG4gICAgY29uc3QgbW9kYWwgPSBuZXcgVXBsb2FkTW9kYWwoXG4gICAgICB0aGlzLmFwcCxcbiAgICAgIGZpbGUsXG4gICAgICB0aGlzLmF1dGhNYW5hZ2VyLFxuICAgICAgdGhpcywgLy8gUGFzcyBwbHVnaW4gaW5zdGFuY2VcbiAgICAgIHRoaXMuc2V0dGluZ3MuZGVmYXVsdFNob3J0Q29kZVByZWZpeFxuICAgICk7XG4gICAgbW9kYWwub3BlbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBzdGF0dXMgYmFyIHdpdGggY3VycmVudCBmaWxlJ3MgdXV1LmdsIGxpbmtcbiAgICovXG4gIHB1YmxpYyBhc3luYyB1cGRhdGVTdGF0dXNCYXIoKSB7XG4gICAgaWYgKCF0aGlzLnN0YXR1c0Jhckl0ZW0pIHJldHVybjtcblxuICAgIGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpO1xuICAgIGlmICghYWN0aXZlRmlsZSkge1xuICAgICAgdGhpcy5zdGF0dXNCYXJJdGVtLnNldFRleHQoJycpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHVybCA9IGF3YWl0IHRoaXMuZ2V0VXV1Z2xMaW5rRnJvbUZpbGUoYWN0aXZlRmlsZSk7XG4gICAgaWYgKHVybCkge1xuICAgICAgLy8gRXh0cmFjdCBzaG9ydENvZGUgZnJvbSBVUkwgZm9yIGNvbXBhY3QgZGlzcGxheVxuICAgICAgY29uc3Qgc2hvcnRDb2RlID0gdXJsLnJlcGxhY2UoJ2h0dHBzOi8vdXV1LmdsLycsICcnKTtcbiAgICAgIHRoaXMuc3RhdHVzQmFySXRlbS5zZXRUZXh0KGBcdUQ4M0RcdUREMTcgJHtzaG9ydENvZGV9YCk7XG4gICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc2V0QXR0cmlidXRlKCd0aXRsZScsIGBDbGljayB0byBjb3B5OiAke3VybH1gKTtcblxuICAgICAgLy8gTWFrZSBpdCBjbGlja2FibGUgdG8gY29weSBVUkxcbiAgICAgIHRoaXMuc3RhdHVzQmFySXRlbS5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh1cmwpO1xuICAgICAgICBuZXcgTm90aWNlKCdcdUQ4M0RcdURDQ0UgdXV1LmdsIGxpbmsgY29waWVkIHRvIGNsaXBib2FyZCEnKTtcbiAgICAgIH07XG4gICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc3R5bGUuY3Vyc29yID0gJ3BvaW50ZXInO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc2V0VGV4dCgnJyk7XG4gICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0ub25jbGljayA9IG51bGw7XG4gICAgICB0aGlzLnN0YXR1c0Jhckl0ZW0uc3R5bGUuY3Vyc29yID0gJ2RlZmF1bHQnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdXV1LmdsIGxpbmsgZnJvbSBtZW1vcnkgY2FjaGUgb3IgZmlsZSdzIGZyb250bWF0dGVyXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGdldFV1dWdsTGlua0Zyb21GaWxlKGZpbGU6IFRGaWxlKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEZpcnN0IGNoZWNrIG1lbW9yeSBjYWNoZVxuICAgICAgY29uc3QgY2FjaGVkVXJsID0gdGhpcy51cmxDYWNoZS5nZXQoZmlsZS5wYXRoKTtcbiAgICAgIGlmIChjYWNoZWRVcmwpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZFVybDtcbiAgICAgIH1cblxuICAgICAgLy8gVGhlbiBjaGVjayBmcm9udG1hdHRlclxuICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlYWQoZmlsZSk7XG5cbiAgICAgIC8vIFBhcnNlIGZyb250bWF0dGVyXG4gICAgICBjb25zdCBmcm9udG1hdHRlclJlZ2V4ID0gL14tLS1cXG4oW1xcc1xcU10qPylcXG4tLS0vO1xuICAgICAgY29uc3QgbWF0Y2ggPSBjb250ZW50Lm1hdGNoKGZyb250bWF0dGVyUmVnZXgpO1xuXG4gICAgICBpZiAoIW1hdGNoKSByZXR1cm4gbnVsbDtcblxuICAgICAgY29uc3QgZnJvbnRtYXR0ZXIgPSBtYXRjaFsxXTtcbiAgICAgIGNvbnN0IGxpbmVzID0gZnJvbnRtYXR0ZXIuc3BsaXQoJ1xcbicpO1xuXG4gICAgICAvLyBGaW5kIHV1dWdsIGZpZWxkXG4gICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHtcbiAgICAgICAgaWYgKGxpbmUuc3RhcnRzV2l0aCgndXV1Z2w6JykpIHtcbiAgICAgICAgICBjb25zdCB1cmwgPSBsaW5lLnJlcGxhY2UoJ3V1dWdsOicsICcnKS50cmltKCk7XG4gICAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgICAgLy8gQ2FjaGUgaXQgZm9yIGZ1dHVyZSB1c2VcbiAgICAgICAgICAgIHRoaXMudXJsQ2FjaGUuc2V0KGZpbGUucGF0aCwgdXJsKTtcbiAgICAgICAgICAgIHJldHVybiB1cmw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gcmVhZCB1dXUuZ2wgbGluazonLCBlcnJvcik7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IHV1dS5nbCBVUkwgZm9yIGEgZmlsZSAoaW4gbWVtb3J5IGNhY2hlIG9ubHkpXG4gICAqL1xuICBwdWJsaWMgc2V0VXV1Z2xVcmwoZmlsZTogVEZpbGUsIHVybDogc3RyaW5nKSB7XG4gICAgdGhpcy51cmxDYWNoZS5zZXQoZmlsZS5wYXRoLCB1cmwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB1dXUuZ2wgVVJMIGZyb20gY2FjaGVcbiAgICovXG4gIHB1YmxpYyByZW1vdmVVdXVnbFVybChmaWxlOiBURmlsZSkge1xuICAgIHRoaXMudXJsQ2FjaGUuZGVsZXRlKGZpbGUucGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSBVUkwgY2FjaGUgdG8gcGVyc2lzdGVudCBzZXR0aW5ncyBzdG9yYWdlXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2F2ZVVybENhY2hlKCkge1xuICAgIC8vIENvbnZlcnQgTWFwIHRvIHBsYWluIG9iamVjdFxuICAgIGNvbnN0IGNhY2hlT2JqZWN0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgZm9yIChjb25zdCBbZmlsZVBhdGgsIHVybF0gb2YgdGhpcy51cmxDYWNoZS5lbnRyaWVzKCkpIHtcbiAgICAgIGNhY2hlT2JqZWN0W2ZpbGVQYXRoXSA9IHVybDtcbiAgICB9XG5cbiAgICAvLyBTYXZlIHRvIHNldHRpbmdzXG4gICAgdGhpcy5zZXR0aW5ncy51cmxDYWNoZSA9IGNhY2hlT2JqZWN0O1xuICAgIGF3YWl0IHRoaXMuc2F2ZVNldHRpbmdzKCk7XG5cbiAgICBjb25zb2xlLmxvZyhgXHVEODNEXHVEQ0JFIFNhdmVkICR7dGhpcy51cmxDYWNoZS5zaXplfSBVUkxzIHRvIHBlcnNpc3RlbnQgc3RvcmFnZWApO1xuICB9XG59XG4iLCAiLyoqXG4gKiBBdXRoTWFuYWdlciAtIE1vYmlsZSBDb21wYXRpYmxlIFZlcnNpb25cbiAqIEhhbmRsZXMgRmlyZWJhc2UgYXV0aGVudGljYXRpb24gdXNpbmcgb2JzaWRpYW46Ly8gVVJMIHNjaGVtZVxuICogV29ya3Mgb24gRGVza3RvcCAoRWxlY3Ryb24pLCBpT1MsIGFuZCBBbmRyb2lkXG4gKi9cblxuaW1wb3J0IHsgYXV0aCB9IGZyb20gJy4vZmlyZWJhc2UtY29uZmlnJztcbmltcG9ydCB7IHNpZ25JbldpdGhDdXN0b21Ub2tlbiB9IGZyb20gJ2ZpcmViYXNlL2F1dGgnO1xuaW1wb3J0IHsgTm90aWNlLCBQbGF0Zm9ybSB9IGZyb20gJ29ic2lkaWFuJztcblxuZXhwb3J0IGludGVyZmFjZSBBdXRoVXNlciB7XG4gIHVpZDogc3RyaW5nO1xuICBlbWFpbDogc3RyaW5nIHwgbnVsbDtcbiAgZGlzcGxheU5hbWU6IHN0cmluZyB8IG51bGw7XG4gIHBob3RvVVJMOiBzdHJpbmcgfCBudWxsO1xufVxuXG5leHBvcnQgY2xhc3MgQXV0aE1hbmFnZXIge1xuICBwcml2YXRlIGF1dGhDYWxsYmFja3M6IE1hcDxzdHJpbmcsICh0b2tlbjogc3RyaW5nKSA9PiB2b2lkPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBBVVRIX1VSTCA9ICdodHRwczovL3V1dS5nbC9hdXRoL29ic2lkaWFuJztcblxuICAvKipcbiAgICogU2lnbiBpbiB3aXRoIEdvb2dsZSBPQXV0aCAoY3Jvc3MtcGxhdGZvcm0pXG4gICAqIE9wZW5zIGJyb3dzZXIgZm9yIGF1dGhlbnRpY2F0aW9uLCByZXR1cm5zIHRvIE9ic2lkaWFuIHZpYSBvYnNpZGlhbjovLyBVUkxcbiAgICovXG4gIGFzeW5jIHNpZ25JbldpdGhHb29nbGUoKTogUHJvbWlzZTxBdXRoVXNlcj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBHZW5lcmF0ZSB1bmlxdWUgY2FsbGJhY2sgSURcbiAgICAgIGNvbnN0IGNhbGxiYWNrSWQgPSBgYXV0aC0ke0RhdGUubm93KCl9LSR7TWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDIsIDExKX1gO1xuXG4gICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVERDEwIFN0YXJ0aW5nIGNyb3NzLXBsYXRmb3JtIE9BdXRoIGZsb3cuLi4nKTtcblxuICAgICAgLy8gUmVnaXN0ZXIgY2FsbGJhY2tcbiAgICAgIHRoaXMuYXV0aENhbGxiYWNrcy5zZXQoY2FsbGJhY2tJZCwgYXN5bmMgKGN1c3RvbVRva2VuOiBzdHJpbmcpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVERDExIFJlY2VpdmVkIGN1c3RvbSB0b2tlbiwgYXV0aGVudGljYXRpbmcgd2l0aCBGaXJlYmFzZS4uLicpO1xuXG4gICAgICAgICAgLy8gU2lnbiBpbiB3aXRoIGN1c3RvbSB0b2tlblxuICAgICAgICAgIGNvbnN0IHVzZXJDcmVkZW50aWFsID0gYXdhaXQgc2lnbkluV2l0aEN1c3RvbVRva2VuKGF1dGgsIGN1c3RvbVRva2VuKTtcbiAgICAgICAgICBjb25zdCB1c2VyID0gdXNlckNyZWRlbnRpYWwudXNlcjtcblxuICAgICAgICAgIGNvbnNvbGUubG9nKCdcdTI3MDUgRmlyZWJhc2UgYXV0aGVudGljYXRpb24gc3VjY2Vzc2Z1bDonLCB1c2VyLmVtYWlsKTtcblxuICAgICAgICAgIGNvbnN0IGF1dGhVc2VyOiBBdXRoVXNlciA9IHtcbiAgICAgICAgICAgIHVpZDogdXNlci51aWQsXG4gICAgICAgICAgICBlbWFpbDogdXNlci5lbWFpbCxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiB1c2VyLmRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgcGhvdG9VUkw6IHVzZXIucGhvdG9VUkwsXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIC8vIENsZWFuIHVwIGNhbGxiYWNrXG4gICAgICAgICAgdGhpcy5hdXRoQ2FsbGJhY2tzLmRlbGV0ZShjYWxsYmFja0lkKTtcblxuICAgICAgICAgIHJlc29sdmUoYXV0aFVzZXIpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignXHUyNzRDIEZpcmViYXNlIGF1dGhlbnRpY2F0aW9uIGZhaWxlZDonLCBlcnJvcik7XG4gICAgICAgICAgdGhpcy5hdXRoQ2FsbGJhY2tzLmRlbGV0ZShjYWxsYmFja0lkKTtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy8gQnVpbGQgYXV0aCBVUkwgd2l0aCBjYWxsYmFja1xuICAgICAgY29uc3QgYXV0aFVybCA9IGAke3RoaXMuQVVUSF9VUkx9P2NhbGxiYWNrSWQ9JHtjYWxsYmFja0lkfWA7XG5cbiAgICAgIGNvbnNvbGUubG9nKCdcdUQ4M0RcdUREMTcgT3BlbmluZyBicm93c2VyIGZvciBhdXRoZW50aWNhdGlvbi4uLicpO1xuICAgICAgY29uc29sZS5sb2coJ1BsYXRmb3JtOicsIFBsYXRmb3JtLmlzRGVza3RvcEFwcCA/ICdEZXNrdG9wJyA6IFBsYXRmb3JtLmlzTW9iaWxlQXBwID8gJ01vYmlsZScgOiAnVW5rbm93bicpO1xuXG4gICAgICAvLyBPcGVuIGJyb3dzZXIgKGNyb3NzLXBsYXRmb3JtKVxuICAgICAgdGhpcy5vcGVuRXh0ZXJuYWxCcm93c2VyKGF1dGhVcmwpO1xuXG4gICAgICAvLyBUaW1lb3V0IGFmdGVyIDUgbWludXRlc1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmF1dGhDYWxsYmFja3MuaGFzKGNhbGxiYWNrSWQpKSB7XG4gICAgICAgICAgdGhpcy5hdXRoQ2FsbGJhY2tzLmRlbGV0ZShjYWxsYmFja0lkKTtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdBdXRoZW50aWNhdGlvbiB0aW1lb3V0JykpO1xuICAgICAgICB9XG4gICAgICB9LCA1ICogNjAgKiAxMDAwKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVuIGV4dGVybmFsIGJyb3dzZXIgKGNyb3NzLXBsYXRmb3JtKVxuICAgKi9cbiAgcHJpdmF0ZSBvcGVuRXh0ZXJuYWxCcm93c2VyKHVybDogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChQbGF0Zm9ybS5pc0Rlc2t0b3BBcHApIHtcbiAgICAgICAgLy8gRGVza3RvcDogVXNlIEVsZWN0cm9uIHNoZWxsXG4gICAgICAgIGNvbnN0IHsgc2hlbGwgfSA9IHJlcXVpcmUoJ2VsZWN0cm9uJyk7XG4gICAgICAgIHNoZWxsLm9wZW5FeHRlcm5hbCh1cmwpO1xuICAgICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVEREE1XHVGRTBGIE9wZW5lZCBicm93c2VyIHZpYSBFbGVjdHJvbiBzaGVsbCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gTW9iaWxlOiBVc2UgT2JzaWRpYW4ncyBidWlsdC1pbiBtZXRob2RcbiAgICAgICAgY29uc3QgZ2xvYmFsV2luZG93ID0gd2luZG93IGFzIGFueTtcbiAgICAgICAgaWYgKGdsb2JhbFdpbmRvdy5hcHAgJiYgdHlwZW9mIGdsb2JhbFdpbmRvdy5hcHAub3BlbkV4dGVybmFsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgZ2xvYmFsV2luZG93LmFwcC5vcGVuRXh0ZXJuYWwodXJsKTtcbiAgICAgICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVEQ0YxIE9wZW5lZCBicm93c2VyIHZpYSBPYnNpZGlhbiBtb2JpbGUgQVBJJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRmFsbGJhY2s6IFRyeSB3aW5kb3cub3BlblxuICAgICAgICAgIHdpbmRvdy5vcGVuKHVybCwgJ19ibGFuaycpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdcdUQ4M0NcdURGMTAgT3BlbmVkIGJyb3dzZXIgdmlhIHdpbmRvdy5vcGVuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcdTI3NEMgRmFpbGVkIHRvIG9wZW4gYnJvd3NlcjonLCBlcnJvcik7XG4gICAgICBuZXcgTm90aWNlKCdGYWlsZWQgdG8gb3BlbiBicm93c2VyLiBQbGVhc2Ugb3BlbiB0aGlzIGxpbmsgbWFudWFsbHk6Jyk7XG4gICAgICBuZXcgTm90aWNlKHVybCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBvYnNpZGlhbjovLyBVUkwgY2FsbGJhY2tcbiAgICogQ2FsbGVkIGJ5IG1haW4udHMgd2hlbiBVUkkgaXMgb3BlbmVkXG4gICAqL1xuICBoYW5kbGVDYWxsYmFjayh1cmk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVERDE3IEhhbmRsaW5nIGNhbGxiYWNrIFVSSTonLCB1cmkpO1xuXG4gICAgICAvLyBQYXJzZSBVUkk6IG9ic2lkaWFuOi8vdXV1Z2wtdXBsb2FkZXIvY2FsbGJhY2s/Y2FsbGJhY2tJZD14eHgmdG9rZW49eXl5XG4gICAgICBjb25zdCB1cmwgPSBuZXcgVVJMKHVyaSk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgb3VyIGF1dGggY2FsbGJhY2tcbiAgICAgIGlmICghdXJsLnBhdGhuYW1lLmluY2x1ZGVzKCdjYWxsYmFjaycpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FsbGJhY2tJZCA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdjYWxsYmFja0lkJyk7XG4gICAgICBjb25zdCB0b2tlbiA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCd0b2tlbicpO1xuICAgICAgY29uc3QgZXJyb3IgPSB1cmwuc2VhcmNoUGFyYW1zLmdldCgnZXJyb3InKTtcblxuICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1x1Mjc0QyBBdXRoIGNhbGxiYWNrIGVycm9yOicsIGVycm9yKTtcbiAgICAgICAgbmV3IE5vdGljZShgXHUyNzRDIEF1dGhlbnRpY2F0aW9uIGZhaWxlZDogJHtlcnJvcn1gKTtcblxuICAgICAgICAvLyBDbGVhciBhbGwgcGVuZGluZyBjYWxsYmFja3NcbiAgICAgICAgdGhpcy5hdXRoQ2FsbGJhY2tzLmNsZWFyKCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghY2FsbGJhY2tJZCB8fCAhdG9rZW4pIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignXHUyNzRDIEludmFsaWQgY2FsbGJhY2sgVVJJOiBtaXNzaW5nIGNhbGxiYWNrSWQgb3IgdG9rZW4nKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBGaW5kIGFuZCBleGVjdXRlIGNhbGxiYWNrXG4gICAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMuYXV0aENhbGxiYWNrcy5nZXQoY2FsbGJhY2tJZCk7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1x1MjcwNSBGb3VuZCBjYWxsYmFjaywgZXhlY3V0aW5nLi4uJyk7XG4gICAgICAgIGNhbGxiYWNrKHRva2VuKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1x1MjZBMFx1RkUwRiBObyBjYWxsYmFjayBmb3VuZCBmb3IgY2FsbGJhY2tJZDonLCBjYWxsYmFja0lkKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1x1Mjc0QyBGYWlsZWQgdG8gaGFuZGxlIGNhbGxiYWNrOicsIGVycm9yKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2lnbiBvdXRcbiAgICovXG4gIGFzeW5jIHNpZ25PdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgYXV0aC5zaWduT3V0KCk7XG4gICAgY29uc29sZS5sb2coJ1x1RDgzRFx1REM0QiBTaWduZWQgb3V0Jyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGN1cnJlbnQgYXV0aGVudGljYXRlZCB1c2VyXG4gICAqL1xuICBnZXRDdXJyZW50VXNlcigpOiBBdXRoVXNlciB8IG51bGwge1xuICAgIGNvbnN0IHVzZXIgPSBhdXRoLmN1cnJlbnRVc2VyO1xuICAgIGlmICghdXNlcikgcmV0dXJuIG51bGw7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdWlkOiB1c2VyLnVpZCxcbiAgICAgIGVtYWlsOiB1c2VyLmVtYWlsLFxuICAgICAgZGlzcGxheU5hbWU6IHVzZXIuZGlzcGxheU5hbWUsXG4gICAgICBwaG90b1VSTDogdXNlci5waG90b1VSTCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IGF1dGhlbnRpY2F0ZWQgdXNlciBlbWFpbFxuICAgKi9cbiAgZ2V0Q3VycmVudFVzZXJFbWFpbCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gYXV0aC5jdXJyZW50VXNlcj8uZW1haWwgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB1c2VyIGlzIGF1dGhlbnRpY2F0ZWRcbiAgICovXG4gIGlzQXV0aGVudGljYXRlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISFhdXRoLmN1cnJlbnRVc2VyO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBGaXJlYmFzZSBJRCB0b2tlblxuICAgKi9cbiAgYXN5bmMgZ2V0SWRUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHRva2VuID0gYXdhaXQgYXV0aC5jdXJyZW50VXNlcj8uZ2V0SWRUb2tlbigpO1xuICAgIGlmICghdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYXV0aGVudGljYXRpb24gdG9rZW4gYXZhaWxhYmxlJyk7XG4gICAgfVxuICAgIHJldHVybiB0b2tlbjtcbiAgfVxufVxuIiwgIi8qKlxuICogVXBsb2FkIE1vZGFsXG4gKiBTaG93cyBwcm9ncmVzcyBhbmQgYWxsb3dzIHVzZXIgdG8gc3BlY2lmeSBzaG9ydGNvZGVcbiAqIERldGVjdHMgZXhpc3RpbmcgdXV1LmdsIGxpbmtzIGFuZCBvZmZlcnMgdXBkYXRlL2RlbGV0ZSBvcHRpb25zXG4gKi9cblxuaW1wb3J0IHsgQXBwLCBNb2RhbCwgTm90aWNlLCBURmlsZSB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IE1hcmtkb3duRXh0cmFjdG9yIH0gZnJvbSAnLi9tYXJrZG93bi1leHRyYWN0b3InO1xuaW1wb3J0IHsgSW1hZ2VVcGxvYWRlciB9IGZyb20gJy4vaW1hZ2UtdXBsb2FkZXInO1xuaW1wb3J0IHsgTWVtb1VwbG9hZGVyIH0gZnJvbSAnLi9tZW1vLXVwbG9hZGVyJztcbmltcG9ydCB7IEF1dGhNYW5hZ2VyIH0gZnJvbSAnLi9hdXRoLW1hbmFnZXInO1xuaW1wb3J0IHsgaHR0cHNDYWxsYWJsZSB9IGZyb20gJ2ZpcmViYXNlL2Z1bmN0aW9ucyc7XG5pbXBvcnQgeyBmdW5jdGlvbnMgfSBmcm9tICcuL2ZpcmViYXNlLWNvbmZpZyc7XG5pbXBvcnQgdHlwZSBVdXVnbFBsdWdpbiBmcm9tICcuL21haW4nO1xuXG5leHBvcnQgY2xhc3MgVXBsb2FkTW9kYWwgZXh0ZW5kcyBNb2RhbCB7XG4gIHByaXZhdGUgZmlsZTogVEZpbGU7XG4gIHByaXZhdGUgYXV0aE1hbmFnZXI6IEF1dGhNYW5hZ2VyO1xuICBwcml2YXRlIGRlZmF1bHRQcmVmaXg6IHN0cmluZztcbiAgcHJpdmF0ZSBwbHVnaW46IFV1dWdsUGx1Z2luO1xuICBwcml2YXRlIGtleXdvcmQxSW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBrZXl3b3JkMklucHV0OiBIVE1MSW5wdXRFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcGFzc3dvcmRJbnB1dDogSFRNTElucHV0RWxlbWVudCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHVybFByZXZpZXdFbDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwcm9ncmVzc0VsOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHByb2dyZXNzQmFyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHByb2dyZXNzVGV4dDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZXN1bHRFbDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBtYWluQ29udGVudDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBleGlzdGluZ1VybDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgYXBwOiBBcHAsXG4gICAgZmlsZTogVEZpbGUsXG4gICAgYXV0aE1hbmFnZXI6IEF1dGhNYW5hZ2VyLFxuICAgIHBsdWdpbjogVXV1Z2xQbHVnaW4sXG4gICAgZGVmYXVsdFByZWZpeDogc3RyaW5nID0gJ29ic2lkaWFuJ1xuICApIHtcbiAgICBzdXBlcihhcHApO1xuICAgIHRoaXMuZmlsZSA9IGZpbGU7XG4gICAgdGhpcy5hdXRoTWFuYWdlciA9IGF1dGhNYW5hZ2VyO1xuICAgIHRoaXMucGx1Z2luID0gcGx1Z2luO1xuICAgIHRoaXMuZGVmYXVsdFByZWZpeCA9IGRlZmF1bHRQcmVmaXg7XG4gIH1cblxuICBhc3luYyBvbk9wZW4oKSB7XG4gICAgY29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XG4gICAgY29udGVudEVsLmFkZENsYXNzKCd1dXVnbC11cGxvYWQtbW9kYWwnKTtcblxuICAgIC8vIEhlYWRlciBzZWN0aW9uXG4gICAgY29uc3QgaGVhZGVyID0gY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLW1vZGFsLWhlYWRlcicgfSk7XG4gICAgaGVhZGVyLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ1VwbG9hZCBub3RlIHRvIHV1dS5nbCcgfSk7XG4gICAgaGVhZGVyLmNyZWF0ZUVsKCdwJywge1xuICAgICAgdGV4dDogYEZpbGU6ICR7dGhpcy5maWxlLmJhc2VuYW1lfWAsXG4gICAgICBjbHM6ICd1dXVnbC1maWxlLW5hbWUnLFxuICAgIH0pO1xuXG4gICAgLy8gTWFpbiBjb250ZW50IHNlY3Rpb25cbiAgICB0aGlzLm1haW5Db250ZW50ID0gY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLW1vZGFsLWNvbnRlbnQnIH0pO1xuXG4gICAgLy8gUHJvZ3Jlc3MgY29udGFpbmVyXG4gICAgdGhpcy5wcm9ncmVzc0VsID0gY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLXByb2dyZXNzJyB9KTtcbiAgICB0aGlzLnByb2dyZXNzVGV4dCA9IHRoaXMucHJvZ3Jlc3NFbC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1wcm9ncmVzcy10ZXh0JyB9KTtcbiAgICBjb25zdCBwcm9ncmVzc0JhckNvbnRhaW5lciA9IHRoaXMucHJvZ3Jlc3NFbC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1wcm9ncmVzcy1iYXItY29udGFpbmVyJyB9KTtcbiAgICB0aGlzLnByb2dyZXNzQmFyID0gcHJvZ3Jlc3NCYXJDb250YWluZXIuY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtcHJvZ3Jlc3MtYmFyLWZpbGwnIH0pO1xuICAgIHRoaXMucHJvZ3Jlc3NFbC5oaWRlKCk7XG5cbiAgICAvLyBSZXN1bHQgY29udGFpbmVyXG4gICAgdGhpcy5yZXN1bHRFbCA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1yZXN1bHQnIH0pO1xuICAgIHRoaXMucmVzdWx0RWwuaGlkZSgpO1xuXG4gICAgLy8gQ2hlY2sgZm9yIGV4aXN0aW5nIG1lbW9cbiAgICB0aGlzLmV4aXN0aW5nVXJsID0gYXdhaXQgdGhpcy5jaGVja0V4aXN0aW5nTWVtbygpO1xuXG4gICAgaWYgKHRoaXMuZXhpc3RpbmdVcmwpIHtcbiAgICAgIC8vIFNob3cgZXhpc3RpbmcgbWVtbyBVSVxuICAgICAgdGhpcy5yZW5kZXJFeGlzdGluZ01lbW9VSSh0aGlzLmV4aXN0aW5nVXJsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU2hvdyBuZXcgbWVtbyB1cGxvYWQgVUlcbiAgICAgIHRoaXMucmVuZGVyTmV3TWVtb1VJKCk7XG4gICAgfVxuICB9XG5cbiAgb25DbG9zZSgpIHtcbiAgICBjb25zdCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcbiAgICBjb250ZW50RWwuZW1wdHkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgZmlsZSBhbHJlYWR5IGhhcyBhIHV1dS5nbCBsaW5rIChtZW1vcnkgY2FjaGUgb3IgZnJvbnRtYXR0ZXIpXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNoZWNrRXhpc3RpbmdNZW1vKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBGaXJzdCBjaGVjayBtZW1vcnkgY2FjaGVcbiAgICAgIGNvbnN0IGNhY2hlZFVybCA9IHRoaXMucGx1Z2luLnVybENhY2hlLmdldCh0aGlzLmZpbGUucGF0aCk7XG4gICAgICBpZiAoY2FjaGVkVXJsKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdcdTI3MDUgRm91bmQgVVJMIGluIG1lbW9yeSBjYWNoZTonLCBjYWNoZWRVcmwpO1xuICAgICAgICByZXR1cm4gY2FjaGVkVXJsO1xuICAgICAgfVxuXG4gICAgICAvLyBUaGVuIGNoZWNrIGZyb250bWF0dGVyXG4gICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQucmVhZCh0aGlzLmZpbGUpO1xuXG4gICAgICAvLyBQYXJzZSBmcm9udG1hdHRlclxuICAgICAgY29uc3QgZnJvbnRtYXR0ZXJSZWdleCA9IC9eLS0tXFxuKFtcXHNcXFNdKj8pXFxuLS0tLztcbiAgICAgIGNvbnN0IG1hdGNoID0gY29udGVudC5tYXRjaChmcm9udG1hdHRlclJlZ2V4KTtcblxuICAgICAgaWYgKCFtYXRjaCkgcmV0dXJuIG51bGw7XG5cbiAgICAgIGNvbnN0IGZyb250bWF0dGVyID0gbWF0Y2hbMV07XG4gICAgICBjb25zdCBsaW5lcyA9IGZyb250bWF0dGVyLnNwbGl0KCdcXG4nKTtcblxuICAgICAgLy8gRmluZCB1dXVnbCBmaWVsZFxuICAgICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoJ3V1dWdsOicpKSB7XG4gICAgICAgICAgY29uc3QgdXJsID0gbGluZS5yZXBsYWNlKCd1dXVnbDonLCAnJykudHJpbSgpO1xuICAgICAgICAgIGlmICh1cmwpIHtcbiAgICAgICAgICAgIC8vIENhY2hlIGl0IGZvciBmdXR1cmUgdXNlXG4gICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXRVdXVnbFVybCh0aGlzLmZpbGUsIHVybCk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnXHUyNzA1IEZvdW5kIFVSTCBpbiBmcm9udG1hdHRlcjonLCB1cmwpO1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBjaGVjayBleGlzdGluZyBtZW1vOicsIGVycm9yKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgVUkgZm9yIGV4aXN0aW5nIG1lbW8gKENvcHkvVXBkYXRlL0RlbGV0ZSlcbiAgICovXG4gIHByaXZhdGUgcmVuZGVyRXhpc3RpbmdNZW1vVUkodXJsOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMubWFpbkNvbnRlbnQpIHJldHVybjtcblxuICAgIHRoaXMubWFpbkNvbnRlbnQuZW1wdHkoKTtcblxuICAgIC8vIEV4dHJhY3Qgc2hvcnRDb2RlIGZyb20gVVJMXG4gICAgY29uc3Qgc2hvcnRDb2RlID0gdXJsLnJlcGxhY2UoJ2h0dHBzOi8vdXV1LmdsLycsICcnKTtcblxuICAgIC8vIEluZm8gc2VjdGlvblxuICAgIGNvbnN0IGluZm9TZWN0aW9uID0gdGhpcy5tYWluQ29udGVudC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1leGlzdGluZy1tZW1vLXNlY3Rpb24nIH0pO1xuXG4gICAgY29uc3QgaW5mb1RpdGxlID0gaW5mb1NlY3Rpb24uY3JlYXRlRWwoJ2RpdicsIHtcbiAgICAgIHRleHQ6ICdcdTI3MDUgVGhpcyBub3RlIGlzIGFscmVhZHkgdXBsb2FkZWQnLFxuICAgICAgY2xzOiAndXV1Z2wtZXhpc3RpbmctbWVtby10aXRsZSdcbiAgICB9KTtcblxuICAgIGNvbnN0IHVybERpc3BsYXkgPSBpbmZvU2VjdGlvbi5jcmVhdGVFbCgnYScsIHtcbiAgICAgIHRleHQ6IHVybCxcbiAgICAgIGhyZWY6IHVybCxcbiAgICAgIGNsczogJ3V1dWdsLWV4aXN0aW5nLW1lbW8tdXJsJ1xuICAgIH0pO1xuICAgIHVybERpc3BsYXkuc2V0QXR0cmlidXRlKCd0YXJnZXQnLCAnX2JsYW5rJyk7XG5cbiAgICBjb25zdCB1cGxvYWREYXRlID0gdGhpcy5tYWluQ29udGVudC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1leGlzdGluZy1tZW1vLWRhdGUnIH0pO1xuICAgIHVwbG9hZERhdGUuc2V0VGV4dCgnXHVEODNEXHVEREQzXHVGRTBGIFlvdSBjYW4gdXBkYXRlIHRoZSBtZW1vIGNvbnRlbnQgb3IgZGVsZXRlIGl0IHRvIGNyZWF0ZSBhIG5ldyBvbmUnKTtcblxuICAgIC8vIERpdmlkZXJcbiAgICB0aGlzLm1haW5Db250ZW50LmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLXNlY3Rpb24tZGl2aWRlcicgfSk7XG5cbiAgICAvLyBCdXR0b25zIHNlY3Rpb25cbiAgICBjb25zdCBidXR0b25zU2VjdGlvbiA9IHRoaXMubWFpbkNvbnRlbnQuY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtZXhpc3RpbmctbWVtby1idXR0b25zJyB9KTtcblxuICAgIC8vIENvcHkgTGluayBidXR0b25cbiAgICBjb25zdCBjb3B5QnV0dG9uID0gYnV0dG9uc1NlY3Rpb24uY3JlYXRlRWwoJ2J1dHRvbicsIHtcbiAgICAgIHRleHQ6ICdcdUQ4M0RcdURDQ0UgQ29weSBMaW5rJyxcbiAgICAgIGNsczogJ3V1dWdsLWJ0biB1dXVnbC1idG4tc2Vjb25kYXJ5J1xuICAgIH0pO1xuICAgIGNvcHlCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG4gICAgICBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh1cmwpO1xuICAgICAgbmV3IE5vdGljZSgnXHVEODNEXHVEQ0NFIExpbmsgY29waWVkIHRvIGNsaXBib2FyZCEnKTtcbiAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSBNZW1vIGJ1dHRvblxuICAgIGNvbnN0IHVwZGF0ZUJ1dHRvbiA9IGJ1dHRvbnNTZWN0aW9uLmNyZWF0ZUVsKCdidXR0b24nLCB7XG4gICAgICB0ZXh0OiAnXHVEODNEXHVERDA0IFVwZGF0ZSBNZW1vJyxcbiAgICAgIGNsczogJ3V1dWdsLWJ0biB1dXVnbC1idG4tcHJpbWFyeSdcbiAgICB9KTtcbiAgICB1cGRhdGVCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLmhhbmRsZVVwZGF0ZU1lbW8oc2hvcnRDb2RlKSk7XG5cbiAgICAvLyBEZWxldGUgTWVtbyBidXR0b25cbiAgICBjb25zdCBkZWxldGVCdXR0b24gPSBidXR0b25zU2VjdGlvbi5jcmVhdGVFbCgnYnV0dG9uJywge1xuICAgICAgdGV4dDogJ1x1RDgzRFx1REREMVx1RkUwRiBEZWxldGUgTWVtbycsXG4gICAgICBjbHM6ICd1dXVnbC1idG4gdXV1Z2wtYnRuLWRhbmdlcidcbiAgICB9KTtcbiAgICBkZWxldGVCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLmhhbmRsZURlbGV0ZU1lbW8oc2hvcnRDb2RlKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIFVJIGZvciBuZXcgbWVtbyB1cGxvYWRcbiAgICovXG4gIHByaXZhdGUgcmVuZGVyTmV3TWVtb1VJKCkge1xuICAgIGlmICghdGhpcy5tYWluQ29udGVudCkgcmV0dXJuO1xuXG4gICAgdGhpcy5tYWluQ29udGVudC5lbXB0eSgpO1xuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIDEuIFBhc3N3b3JkIFNlY3Rpb24gKE1PVkVEIFRPIFRPUClcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgY29uc3QgcGFzc3dvcmRTZWN0aW9uID0gdGhpcy5tYWluQ29udGVudC5jcmVhdGVEaXYoeyBjbHM6ICdzZXR0aW5nLWl0ZW0gdXV1Z2wtc2V0dGluZy1pdGVtJyB9KTtcblxuICAgIGNvbnN0IHBhc3N3b3JkSW5mbyA9IHBhc3N3b3JkU2VjdGlvbi5jcmVhdGVEaXYoeyBjbHM6ICdzZXR0aW5nLWl0ZW0taW5mbycgfSk7XG4gICAgcGFzc3dvcmRJbmZvLmNyZWF0ZURpdih7IGNsczogJ3NldHRpbmctaXRlbS1uYW1lJywgdGV4dDogJ1Bhc3N3b3JkIHByb3RlY3Rpb24nIH0pO1xuICAgIHBhc3N3b3JkSW5mby5jcmVhdGVEaXYoeyBjbHM6ICdzZXR0aW5nLWl0ZW0tZGVzY3JpcHRpb24nLCB0ZXh0OiAnT3B0aW9uYWw6IFNldCBhIHBhc3N3b3JkIHRvIHByb3RlY3QgeW91ciBub3RlJyB9KTtcblxuICAgIGNvbnN0IHBhc3N3b3JkQ29udHJvbCA9IHBhc3N3b3JkU2VjdGlvbi5jcmVhdGVEaXYoeyBjbHM6ICdzZXR0aW5nLWl0ZW0tY29udHJvbCcgfSk7XG4gICAgdGhpcy5wYXNzd29yZElucHV0ID0gcGFzc3dvcmRDb250cm9sLmNyZWF0ZUVsKCdpbnB1dCcsIHtcbiAgICAgIHR5cGU6ICdwYXNzd29yZCcsXG4gICAgICBwbGFjZWhvbGRlcjogJ0VudGVyIHBhc3N3b3JkIChvcHRpb25hbCknLFxuICAgICAgY2xzOiAndXV1Z2wtcGFzc3dvcmQtaW5wdXQnLFxuICAgIH0pO1xuXG4gICAgLy8gRGl2aWRlciBhZnRlciBwYXNzd29yZFxuICAgIGNvbnN0IGRpdmlkZXIxID0gdGhpcy5tYWluQ29udGVudC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1zZWN0aW9uLWRpdmlkZXInIH0pO1xuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIDIuIFVSTCBPcHRpb25zIFNlY3Rpb25cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgY29uc3QgdXJsT3B0aW9uc0hlYWRlciA9IHRoaXMubWFpbkNvbnRlbnQuY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtc2VjdGlvbi1oZWFkZXInIH0pO1xuICAgIHVybE9wdGlvbnNIZWFkZXIuY3JlYXRlRWwoJ2gzJywgeyB0ZXh0OiAnQ2hvb3NlIFVSTCB0eXBlJywgY2xzOiAndXV1Z2wtc2VjdGlvbi10aXRsZScgfSk7XG4gICAgdXJsT3B0aW9uc0hlYWRlci5jcmVhdGVFbCgncCcsIHtcbiAgICAgIHRleHQ6ICdDcmVhdGUgYSBjdXN0b20gbWVtb3JhYmxlIFVSTCBvciBnZW5lcmF0ZSBhIHJhbmRvbSBzaG9ydCBjb2RlJyxcbiAgICAgIGNsczogJ3V1dWdsLXNlY3Rpb24tZGVzY3JpcHRpb24nXG4gICAgfSk7XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gMi4xIEN1c3RvbSBVUkwgT3B0aW9uXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIGNvbnN0IGN1c3RvbVVybFNlY3Rpb24gPSB0aGlzLm1haW5Db250ZW50LmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLW9wdGlvbi1zZWN0aW9uJyB9KTtcblxuICAgIGNvbnN0IGN1c3RvbVVybExhYmVsID0gY3VzdG9tVXJsU2VjdGlvbi5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1vcHRpb24tbGFiZWwnIH0pO1xuICAgIGN1c3RvbVVybExhYmVsLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnXHVEODNDXHVERkFGIEN1c3RvbSBVUkwnLCBjbHM6ICd1dXVnbC1vcHRpb24tdGl0bGUnIH0pO1xuICAgIGN1c3RvbVVybExhYmVsLmNyZWF0ZUVsKCdzcGFuJywge1xuICAgICAgdGV4dDogJ2tleXdvcmQxL2tleXdvcmQyJyxcbiAgICAgIGNsczogJ3V1dWdsLW9wdGlvbi1iYWRnZSdcbiAgICB9KTtcblxuICAgIGNvbnN0IGN1c3RvbVVybERlc2MgPSBjdXN0b21VcmxTZWN0aW9uLmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLW9wdGlvbi1kZXNjcmlwdGlvbicgfSk7XG4gICAgY3VzdG9tVXJsRGVzYy5zZXRUZXh0KCdDcmVhdGUgYSBtZW1vcmFibGUgVVJMIHdpdGggY3VzdG9tIGtleXdvcmRzJyk7XG5cbiAgICAvLyBVUkwgaW5wdXQgY29udGFpbmVyXG4gICAgY29uc3QgdXJsSW5wdXRDb250YWluZXIgPSBjdXN0b21VcmxTZWN0aW9uLmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLXVybC1pbnB1dC1jb250YWluZXInIH0pO1xuXG4gICAgLy8gUHJlZml4XG4gICAgdXJsSW5wdXRDb250YWluZXIuY3JlYXRlRWwoJ3NwYW4nLCB7XG4gICAgICB0ZXh0OiAndXV1LmdsLycsXG4gICAgICBjbHM6ICd1dXVnbC11cmwtcHJlZml4J1xuICAgIH0pO1xuXG4gICAgLy8gS2V5d29yZCAxIGlucHV0XG4gICAgdGhpcy5rZXl3b3JkMUlucHV0ID0gdXJsSW5wdXRDb250YWluZXIuY3JlYXRlRWwoJ2lucHV0Jywge1xuICAgICAgdHlwZTogJ3RleHQnLFxuICAgICAgcGxhY2Vob2xkZXI6ICdrZXl3b3JkMScsXG4gICAgICBjbHM6ICd1dXVnbC1rZXl3b3JkLWlucHV0JyxcbiAgICB9KTtcblxuICAgIC8vIFNlcGFyYXRvclxuICAgIHVybElucHV0Q29udGFpbmVyLmNyZWF0ZUVsKCdzcGFuJywge1xuICAgICAgdGV4dDogJy8nLFxuICAgICAgY2xzOiAndXV1Z2wtdXJsLXNlcGFyYXRvcidcbiAgICB9KTtcblxuICAgIC8vIEtleXdvcmQgMiBpbnB1dFxuICAgIHRoaXMua2V5d29yZDJJbnB1dCA9IHVybElucHV0Q29udGFpbmVyLmNyZWF0ZUVsKCdpbnB1dCcsIHtcbiAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgIHBsYWNlaG9sZGVyOiAna2V5d29yZDInLFxuICAgICAgY2xzOiAndXV1Z2wta2V5d29yZC1pbnB1dCcsXG4gICAgfSk7XG5cbiAgICAvLyBNYWtlIGN1c3RvbSB1cmwgYnV0dG9uXG4gICAgY29uc3QgY3VzdG9tVXJsQnV0dG9uID0gY3VzdG9tVXJsU2VjdGlvbi5jcmVhdGVFbCgnYnV0dG9uJywge1xuICAgICAgdGV4dDogJ0NyZWF0ZSBDdXN0b20gVVJMJyxcbiAgICAgIGNsczogJ3V1dWdsLWJ0biB1dXVnbC1idG4tcHJpbWFyeScsXG4gICAgfSk7XG4gICAgY3VzdG9tVXJsQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gdGhpcy5oYW5kbGVVcGxvYWQoKSk7XG5cbiAgICAvLyBcIm9yXCIgZGl2aWRlclxuICAgIGNvbnN0IG9yRGl2aWRlciA9IHRoaXMubWFpbkNvbnRlbnQuY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtZGl2aWRlcicgfSk7XG4gICAgb3JEaXZpZGVyLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnb3InIH0pO1xuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIDIuMiBSYW5kb20gVVJMIE9wdGlvblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICBjb25zdCByYW5kb21VcmxTZWN0aW9uID0gdGhpcy5tYWluQ29udGVudC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1vcHRpb24tc2VjdGlvbicgfSk7XG5cbiAgICBjb25zdCByYW5kb21VcmxMYWJlbCA9IHJhbmRvbVVybFNlY3Rpb24uY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtb3B0aW9uLWxhYmVsJyB9KTtcbiAgICByYW5kb21VcmxMYWJlbC5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogJ1x1RDgzQ1x1REZCMiBSYW5kb20gVVJMJywgY2xzOiAndXV1Z2wtb3B0aW9uLXRpdGxlJyB9KTtcbiAgICByYW5kb21VcmxMYWJlbC5jcmVhdGVFbCgnc3BhbicsIHtcbiAgICAgIHRleHQ6ICdRdWljayAmIGVhc3knLFxuICAgICAgY2xzOiAndXV1Z2wtb3B0aW9uLWJhZGdlIHV1dWdsLW9wdGlvbi1iYWRnZS1zZWNvbmRhcnknXG4gICAgfSk7XG5cbiAgICBjb25zdCByYW5kb21VcmxEZXNjID0gcmFuZG9tVXJsU2VjdGlvbi5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1vcHRpb24tZGVzY3JpcHRpb24nIH0pO1xuICAgIHJhbmRvbVVybERlc2Muc2V0VGV4dCgnQXV0b21hdGljYWxseSBnZW5lcmF0ZSBhIHNob3J0IHJhbmRvbSBjb2RlJyk7XG5cbiAgICAvLyBSYW5kb20gVVJMIGJ1dHRvblxuICAgIGNvbnN0IHJhbmRvbUJ1dHRvbiA9IHJhbmRvbVVybFNlY3Rpb24uY3JlYXRlRWwoJ2J1dHRvbicsIHtcbiAgICAgIHRleHQ6ICdHZW5lcmF0ZSBSYW5kb20gVVJMJyxcbiAgICAgIGNsczogJ3V1dWdsLWJ0biB1dXVnbC1idG4tc2Vjb25kYXJ5JyxcbiAgICB9KTtcbiAgICByYW5kb21CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBhc3luYyAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5rZXl3b3JkMUlucHV0ICYmIHRoaXMua2V5d29yZDJJbnB1dCkge1xuICAgICAgICB0aGlzLmtleXdvcmQxSW5wdXQudmFsdWUgPSB0aGlzLmdlbmVyYXRlUmFuZG9tU2hvcnRDb2RlKCk7XG4gICAgICAgIHRoaXMua2V5d29yZDJJbnB1dC52YWx1ZSA9ICcnO1xuICAgICAgICB0aGlzLnVwZGF0ZVVybFByZXZpZXcoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5oYW5kbGVVcGxvYWQoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFNldCBkZWZhdWx0IHNob3J0Y29kZVxuICAgIGNvbnN0IHNhbml0aXplZE5hbWUgPSB0aGlzLnNhbml0aXplU2hvcnRDb2RlKHRoaXMuZmlsZS5iYXNlbmFtZSk7XG4gICAgaWYgKHRoaXMua2V5d29yZDFJbnB1dCAmJiB0aGlzLmtleXdvcmQySW5wdXQpIHtcbiAgICAgIHRoaXMua2V5d29yZDFJbnB1dC52YWx1ZSA9IHRoaXMuZGVmYXVsdFByZWZpeDtcbiAgICAgIHRoaXMua2V5d29yZDJJbnB1dC52YWx1ZSA9IHNhbml0aXplZE5hbWU7XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIHByZXZpZXcgb24gaW5wdXQgY2hhbmdlXG4gICAgdGhpcy5rZXl3b3JkMUlucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JywgKCkgPT4gdGhpcy51cGRhdGVVcmxQcmV2aWV3KCkpO1xuICAgIHRoaXMua2V5d29yZDJJbnB1dC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsICgpID0+IHRoaXMudXBkYXRlVXJsUHJldmlldygpKTtcblxuICAgIC8vIFVSTCBQcmV2aWV3IChoaWRkZW4gYnkgZGVmYXVsdCwgc2hvd24gaW4gdXBkYXRlVXJsUHJldmlldylcbiAgICB0aGlzLnVybFByZXZpZXdFbCA9IHRoaXMuY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogJ3V1dWdsLXVybC1wcmV2aWV3JyB9KTtcbiAgICB0aGlzLnVybFByZXZpZXdFbC5oaWRlKCk7XG5cbiAgICAvLyBGb2N1cyBvbiBrZXl3b3JkMSBpbnB1dFxuICAgIGlmICh0aGlzLmtleXdvcmQxSW5wdXQpIHtcbiAgICAgIHRoaXMua2V5d29yZDFJbnB1dC5mb2N1cygpO1xuICAgICAgdGhpcy5rZXl3b3JkMUlucHV0LnNlbGVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgbWVtbyB1cGRhdGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlVXBkYXRlTWVtbyhzaG9ydENvZGU6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAvLyBTaG93IHByb2dyZXNzXG4gICAgICB0aGlzLnByb2dyZXNzRWw/LnNob3coKTtcbiAgICAgIHRoaXMucmVzdWx0RWw/LmhpZGUoKTtcbiAgICAgIGlmICh0aGlzLm1haW5Db250ZW50KSB0aGlzLm1haW5Db250ZW50LmhpZGUoKTtcblxuICAgICAgLy8gU3RlcCAxOiBBdXRoZW50aWNhdGUgKDEwJSlcbiAgICAgIHRoaXMudXBkYXRlUHJvZ3Jlc3MoJ1x1RDgzRFx1REQxMCBBdXRoZW50aWNhdGluZy4uLicsIDEwKTtcbiAgICAgIGlmICghdGhpcy5hdXRoTWFuYWdlci5pc0F1dGhlbnRpY2F0ZWQoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBhdXRoZW50aWNhdGVkLiBQbGVhc2UgY29uZmlndXJlIHlvdXIgZW1haWwgaW4gc2V0dGluZ3MuJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0ZXAgMjogRXh0cmFjdCBtYXJrZG93biAoMzAlKVxuICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcygnXHVEODNEXHVEQ0M0IEV4dHJhY3RpbmcgbWFya2Rvd24gY29udGVudC4uLicsIDMwKTtcbiAgICAgIGNvbnN0IGV4dHJhY3RvciA9IG5ldyBNYXJrZG93bkV4dHJhY3Rvcih0aGlzLmFwcCwgdGhpcy5hcHAudmF1bHQpO1xuICAgICAgY29uc3QgZXh0cmFjdGVkID0gYXdhaXQgZXh0cmFjdG9yLmV4dHJhY3RNYXJrZG93bih0aGlzLmZpbGUpO1xuXG4gICAgICBjb25zb2xlLmxvZyhgXHVEODNEXHVEQ0NBIEV4dHJhY3RlZDogJHtleHRyYWN0ZWQuaW1hZ2VzLmxlbmd0aH0gaW1hZ2VzLCAke2V4dHJhY3RlZC5pbnRlcm5hbExpbmtzLmxlbmd0aH0gaW50ZXJuYWwgbGlua3NgKTtcblxuICAgICAgLy8gU3RlcCAzOiBHZXQgbWVtb0lkIGZyb20gc2hvcnRDb2RlIHVzaW5nIGdldE1lbW9cbiAgICAgIHRoaXMudXBkYXRlUHJvZ3Jlc3MoJ1x1RDgzRFx1REQwRCBMb29raW5nIHVwIG1lbW8uLi4nLCA1MCk7XG4gICAgICBjb25zdCBtZW1vVXBsb2FkZXIgPSBuZXcgTWVtb1VwbG9hZGVyKCk7XG5cbiAgICAgIC8vIEdldCBtZW1vIHRvIGZpbmQgbWVtb0lkXG4gICAgICBjb25zdCBnZXRNZW1vRm4gPSBodHRwc0NhbGxhYmxlKGZ1bmN0aW9ucywgJ2dldE1lbW8nKTtcbiAgICAgIGNvbnN0IGdldE1lbW9SZXN1bHQgPSBhd2FpdCBnZXRNZW1vRm4oeyBzaG9ydENvZGUgfSk7XG4gICAgICBjb25zdCBtZW1vRGF0YSA9IGdldE1lbW9SZXN1bHQuZGF0YSBhcyBhbnk7XG5cbiAgICAgIGlmICghbWVtb0RhdGEuc3VjY2VzcyB8fCAhbWVtb0RhdGEubWVtbykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01lbW8gbm90IGZvdW5kLiBVbmFibGUgdG8gdXBkYXRlLicpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtZW1vSWQgPSBtZW1vRGF0YS5tZW1vLm1lbW9JZDsgLy8gRml4OiBVc2UgY29ycmVjdCBmaWVsZCBuYW1lXG4gICAgICBjb25zdCBjdXJyZW50VmVyc2lvbiA9IG1lbW9EYXRhLm1lbW8udmVyc2lvbiB8fCAwOyAvLyBHZXQgY3VycmVudCB2ZXJzaW9uXG4gICAgICBjb25zb2xlLmxvZyhgXHVEODNEXHVEQ0REIEZvdW5kIG1lbW8gSUQ6ICR7bWVtb0lkfSwgdmVyc2lvbjogJHtjdXJyZW50VmVyc2lvbn1gKTtcblxuICAgICAgLy8gU3RlcCA0OiBVcGxvYWQgaW1hZ2VzICg3MCUpXG4gICAgICBsZXQgdXBkYXRlZENvbnRlbnQgPSBleHRyYWN0ZWQuY29udGVudDtcbiAgICAgIGlmIChleHRyYWN0ZWQuaW1hZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcyhgXHVEODNEXHVEQ0U0IFVwbG9hZGluZyAke2V4dHJhY3RlZC5pbWFnZXMubGVuZ3RofSBpbWFnZShzKS4uLmAsIDcwKTtcblxuICAgICAgICBjb25zdCBpbWFnZVVwbG9hZGVyID0gbmV3IEltYWdlVXBsb2FkZXIoKTtcbiAgICAgICAgY29uc3QgdXBsb2FkZWRJbWFnZXMgPSBhd2FpdCBpbWFnZVVwbG9hZGVyLnVwbG9hZEltYWdlcyhleHRyYWN0ZWQuaW1hZ2VzLCBtZW1vSWQpO1xuXG4gICAgICAgIC8vIFJlcGxhY2UgaW1hZ2UgcGF0aHMgaW4gY29udGVudFxuICAgICAgICB1cGRhdGVkQ29udGVudCA9IGltYWdlVXBsb2FkZXIucmVwbGFjZUltYWdlUGF0aHMoXG4gICAgICAgICAgZXh0cmFjdGVkLmNvbnRlbnQsXG4gICAgICAgICAgZXh0cmFjdGVkLmltYWdlcyxcbiAgICAgICAgICB1cGxvYWRlZEltYWdlc1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBTdGVwIDU6IFNhdmUgbWVtbyAoOTAlKVxuICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcygnXHVEODNEXHVEQ0JFIFVwZGF0aW5nIG1lbW8uLi4nLCA5MCk7XG4gICAgICBhd2FpdCBtZW1vVXBsb2FkZXIuc2F2ZU1lbW8oXG4gICAgICAgIG1lbW9JZCxcbiAgICAgICAgc2hvcnRDb2RlLFxuICAgICAgICB1cGRhdGVkQ29udGVudCxcbiAgICAgICAgZXh0cmFjdGVkLmltYWdlcy5sZW5ndGggPiAwID8gW10gOiBbXSxcbiAgICAgICAgZXh0cmFjdGVkLmludGVybmFsTGlua3MsXG4gICAgICAgIGN1cnJlbnRWZXJzaW9uLCAvLyBGaXg6IFBhc3MgY3VycmVudCB2ZXJzaW9uIGZvciBwcm9wZXIgdmVyc2lvbiBjb250cm9sXG4gICAgICAgIG51bGwgLy8gUGFzc3dvcmQgbm90IGNoYW5nZWFibGUgb24gdXBkYXRlXG4gICAgICApO1xuXG4gICAgICAvLyBDb21wbGV0ZSAoMTAwJSlcbiAgICAgIHRoaXMudXBkYXRlUHJvZ3Jlc3MoJ1x1MjcwNSBVcGRhdGUgY29tcGxldGUhJywgMTAwKTtcblxuICAgICAgLy8gVXBkYXRlIFVSTCBpbiBtZW1vcnkgY2FjaGVcbiAgICAgIGNvbnN0IGRpc3BsYXlVcmwgPSBgaHR0cHM6Ly91dXUuZ2wvJHtzaG9ydENvZGV9YDtcbiAgICAgIHRoaXMucGx1Z2luLnNldFV1dWdsVXJsKHRoaXMuZmlsZSwgZGlzcGxheVVybCk7XG5cbiAgICAgIC8vIFNhdmUgdG8gcGVyc2lzdGVudCBzdG9yYWdlIChJTVBPUlRBTlQ6IHN1cnZpdmVzIHBsdWdpbiByZXN0YXJ0KVxuICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVVybENhY2hlKCk7XG5cbiAgICAgIC8vIFVwZGF0ZSBzdGF0dXMgYmFyXG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBhd2FpdCB0aGlzLnBsdWdpbi51cGRhdGVTdGF0dXNCYXIoKTtcblxuICAgICAgLy8gU2hvdyBzdWNjZXNzXG4gICAgICB0aGlzLnNob3dTdWNjZXNzKGRpc3BsYXlVcmwsICdNZW1vIHVwZGF0ZWQgc3VjY2Vzc2Z1bGx5IScpO1xuXG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgY29uc29sZS5lcnJvcignXHUyNzRDIFVwZGF0ZSBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgdGhpcy5zaG93RXJyb3IoZXJyb3IubWVzc2FnZSB8fCAnVXBkYXRlIGZhaWxlZCcpO1xuICAgICAgaWYgKHRoaXMubWFpbkNvbnRlbnQpIHRoaXMubWFpbkNvbnRlbnQuc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgbWVtbyBkZWxldGlvblxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVEZWxldGVNZW1vKHNob3J0Q29kZTogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIENvbmZpcm0gZGVsZXRpb25cbiAgICAgIGNvbnN0IGNvbmZpcm1lZCA9IGNvbmZpcm0oXG4gICAgICAgIGBBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoaXMgbWVtbz9cXG5cXG5gICtcbiAgICAgICAgYFVSTDogaHR0cHM6Ly91dXUuZ2wvJHtzaG9ydENvZGV9XFxuXFxuYCArXG4gICAgICAgIGBUaGlzIHdpbGwgcmVtb3ZlIHRoZSBtZW1vIGZyb20gdXV1LmdsIGFuZCBjbGVhciB0aGUgZnJvbnRtYXR0ZXIuIGAgK1xuICAgICAgICBgWW91IGNhbiB0aGVuIGNyZWF0ZSBhIG5ldyBtZW1vIHdpdGggYSBkaWZmZXJlbnQgVVJMLmBcbiAgICAgICk7XG5cbiAgICAgIGlmICghY29uZmlybWVkKSByZXR1cm47XG5cbiAgICAgIC8vIFNob3cgcHJvZ3Jlc3NcbiAgICAgIHRoaXMucHJvZ3Jlc3NFbD8uc2hvdygpO1xuICAgICAgdGhpcy5yZXN1bHRFbD8uaGlkZSgpO1xuICAgICAgaWYgKHRoaXMubWFpbkNvbnRlbnQpIHRoaXMubWFpbkNvbnRlbnQuaGlkZSgpO1xuXG4gICAgICAvLyBTdGVwIDE6IEF1dGhlbnRpY2F0ZVxuICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcygnXHVEODNEXHVERDEwIEF1dGhlbnRpY2F0aW5nLi4uJywgMjApO1xuICAgICAgaWYgKCF0aGlzLmF1dGhNYW5hZ2VyLmlzQXV0aGVudGljYXRlZCgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGF1dGhlbnRpY2F0ZWQuIFBsZWFzZSBjb25maWd1cmUgeW91ciBlbWFpbCBpbiBzZXR0aW5ncy4nKTtcbiAgICAgIH1cblxuICAgICAgLy8gU3RlcCAyOiBEZWxldGUgbWVtbyBmcm9tIHNlcnZlclxuICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcygnXHVEODNEXHVEREQxXHVGRTBGIERlbGV0aW5nIG1lbW8gZnJvbSBzZXJ2ZXIuLi4nLCA1MCk7XG4gICAgICBjb25zdCBkZWxldGVNZW1vRm4gPSBodHRwc0NhbGxhYmxlKGZ1bmN0aW9ucywgJ2RlbGV0ZU1lbW8nKTtcbiAgICAgIGF3YWl0IGRlbGV0ZU1lbW9Gbih7IHNob3J0Q29kZSB9KTtcblxuICAgICAgLy8gQ29tcGxldGVcbiAgICAgIHRoaXMudXBkYXRlUHJvZ3Jlc3MoJ1x1MjcwNSBEZWxldGlvbiBjb21wbGV0ZSEnLCAxMDApO1xuXG4gICAgICAvLyBSZW1vdmUgVVJMIGZyb20gbWVtb3J5IGNhY2hlXG4gICAgICB0aGlzLnBsdWdpbi5yZW1vdmVVdXVnbFVybCh0aGlzLmZpbGUpO1xuXG4gICAgICAvLyBTYXZlIHRvIHBlcnNpc3RlbnQgc3RvcmFnZSAoSU1QT1JUQU5UOiBzdXJ2aXZlcyBwbHVnaW4gcmVzdGFydClcbiAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVVcmxDYWNoZSgpO1xuXG4gICAgICAvLyBVcGRhdGUgc3RhdHVzIGJhciB0byByZW1vdmUgdGhlIGxpbmtcbiAgICAgIC8vIEB0cy1pZ25vcmUgLSB1cGRhdGVTdGF0dXNCYXIgaXMgYSBwdWJsaWMgbWV0aG9kXG4gICAgICBhd2FpdCB0aGlzLnBsdWdpbi51cGRhdGVTdGF0dXNCYXIoKTtcblxuICAgICAgLy8gV2FpdCBhIG1vbWVudCB0aGVuIHN3aXRjaCB0byB1cGxvYWQgVUlcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnByb2dyZXNzRWw/LmhpZGUoKTtcbiAgICAgICAgbmV3IE5vdGljZSgnXHUyNzA1IE1lbW8gZGVsZXRlZCBzdWNjZXNzZnVsbHkhIFlvdSBjYW4gbm93IGNyZWF0ZSBhIG5ldyBvbmUuJyk7XG4gICAgICAgIHRoaXMuZXhpc3RpbmdVcmwgPSBudWxsO1xuICAgICAgICB0aGlzLnJlbmRlck5ld01lbW9VSSgpO1xuICAgICAgICBpZiAodGhpcy5tYWluQ29udGVudCkgdGhpcy5tYWluQ29udGVudC5zaG93KCk7XG4gICAgICB9LCAxMDAwKTtcblxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1x1Mjc0QyBEZWxldGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgdGhpcy5zaG93RXJyb3IoZXJyb3IubWVzc2FnZSB8fCAnRGVsZXRpb24gZmFpbGVkJyk7XG4gICAgICBpZiAodGhpcy5tYWluQ29udGVudCkgdGhpcy5tYWluQ29udGVudC5zaG93KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVVcmxQcmV2aWV3KCkge1xuICAgIGlmICghdGhpcy51cmxQcmV2aWV3RWwgfHwgIXRoaXMua2V5d29yZDFJbnB1dCkgcmV0dXJuO1xuXG4gICAgY29uc3Qga2V5d29yZDEgPSB0aGlzLmtleXdvcmQxSW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGNvbnN0IGtleXdvcmQyID0gdGhpcy5rZXl3b3JkMklucHV0Py52YWx1ZS50cmltKCkgfHwgJyc7XG5cbiAgICBsZXQgcHJldmlld1VybCA9ICdodHRwczovL3V1dS5nbC8nO1xuICAgIGlmIChrZXl3b3JkMSAmJiBrZXl3b3JkMikge1xuICAgICAgLy8gQm90aCBrZXl3b3JkczogdXV1LmdsL2tleXdvcmQxL2tleXdvcmQyXG4gICAgICBwcmV2aWV3VXJsICs9IGAke2tleXdvcmQxfS8ke2tleXdvcmQyfWA7XG4gICAgfSBlbHNlIGlmIChrZXl3b3JkMSkge1xuICAgICAgLy8gU2luZ2xlIGtleXdvcmQgKGUuZy4sIHJhbmRvbSk6IHV1dS5nbC9rZXl3b3JkMVxuICAgICAgcHJldmlld1VybCArPSBrZXl3b3JkMTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gTm8gaW5wdXQgeWV0XG4gICAgICBwcmV2aWV3VXJsICs9ICdbZW50ZXIta2V5d29yZF0nO1xuICAgIH1cblxuICAgIHRoaXMudXJsUHJldmlld0VsLmVtcHR5KCk7XG4gICAgdGhpcy51cmxQcmV2aWV3RWwuY3JlYXRlRWwoJ3NwYW4nLCB7XG4gICAgICB0ZXh0OiBgXHVEODNEXHVEQ0NFIFlvdXIgbm90ZSB3aWxsIGJlIGFjY2Vzc2libGUgYXQ6IGAsXG4gICAgICBjbHM6ICd1cGxvYWQtbW9kYWwtdXJsLWxhYmVsJyxcbiAgICB9KTtcbiAgICBjb25zdCB1cmxUZXh0ID0gdGhpcy51cmxQcmV2aWV3RWwuY3JlYXRlRWwoJ3NwYW4nLCB7XG4gICAgICB0ZXh0OiBwcmV2aWV3VXJsLFxuICAgICAgY2xzOiAndXBsb2FkLW1vZGFsLXVybC10ZXh0JyxcbiAgICB9KTtcbiAgICB1cmxUZXh0LnN0eWxlLmZvbnRXZWlnaHQgPSAnYm9sZCc7XG4gICAgdXJsVGV4dC5zdHlsZS5jb2xvciA9ICcjNWIyMWI2JztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlVXBsb2FkKCkge1xuICAgIGlmICghdGhpcy5rZXl3b3JkMUlucHV0KSByZXR1cm47XG5cbiAgICBjb25zdCBrZXl3b3JkMSA9IHRoaXMua2V5d29yZDFJbnB1dC52YWx1ZS50cmltKCk7XG4gICAgY29uc3Qga2V5d29yZDIgPSB0aGlzLmtleXdvcmQySW5wdXQ/LnZhbHVlLnRyaW0oKSB8fCAnJztcbiAgICBjb25zdCBwYXNzd29yZCA9IHRoaXMucGFzc3dvcmRJbnB1dD8udmFsdWUudHJpbSgpIHx8IG51bGw7XG5cbiAgICAvLyBrZXl3b3JkMSBpcyByZXF1aXJlZFxuICAgIGlmICgha2V5d29yZDEpIHtcbiAgICAgIG5ldyBOb3RpY2UoJ1BsZWFzZSBlbnRlciBrZXl3b3JkMScpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEJ1aWxkIHNob3J0Q29kZTogc2luZ2xlIGNvZGUgb3Iga2V5d29yZDEva2V5d29yZDJcbiAgICBjb25zdCBzaG9ydENvZGUgPSBrZXl3b3JkMiA/IGAke2tleXdvcmQxfS8ke2tleXdvcmQyfWAgOiBrZXl3b3JkMTtcblxuICAgIC8vIFZhbGlkYXRlIGtleXdvcmQxXG4gICAgaWYgKCEvXlthLXpBLVowLTlcdUFDMDAtXHVEN0EzXy1dKyQvLnRlc3Qoa2V5d29yZDEpKSB7XG4gICAgICBuZXcgTm90aWNlKCdLZXl3b3JkMSBjYW4gb25seSBjb250YWluIGxldHRlcnMsIG51bWJlcnMsIEtvcmVhbiwgXywgYW5kIC0nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBrZXl3b3JkMiBpZiBwcm92aWRlZFxuICAgIGlmIChrZXl3b3JkMiAmJiAhL15bYS16QS1aMC05XHVBQzAwLVx1RDdBM18tXSskLy50ZXN0KGtleXdvcmQyKSkge1xuICAgICAgbmV3IE5vdGljZSgnS2V5d29yZDIgY2FuIG9ubHkgY29udGFpbiBsZXR0ZXJzLCBudW1iZXJzLCBLb3JlYW4sIF8sIGFuZCAtJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIFNob3cgcHJvZ3Jlc3NcbiAgICAgIHRoaXMucHJvZ3Jlc3NFbD8uc2hvdygpO1xuICAgICAgdGhpcy5yZXN1bHRFbD8uaGlkZSgpO1xuICAgICAgaWYgKHRoaXMubWFpbkNvbnRlbnQpIHRoaXMubWFpbkNvbnRlbnQuaGlkZSgpO1xuXG4gICAgICAvLyBTdGVwIDE6IEF1dGhlbnRpY2F0ZSAoMTAlKVxuICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcygnXHVEODNEXHVERDEwIEF1dGhlbnRpY2F0aW5nLi4uJywgMTApO1xuICAgICAgaWYgKCF0aGlzLmF1dGhNYW5hZ2VyLmlzQXV0aGVudGljYXRlZCgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGF1dGhlbnRpY2F0ZWQuIFBsZWFzZSBjb25maWd1cmUgeW91ciBlbWFpbCBpbiBzZXR0aW5ncy4nKTtcbiAgICAgIH1cblxuICAgICAgLy8gU3RlcCAyOiBFeHRyYWN0IG1hcmtkb3duICgzMCUpXG4gICAgICB0aGlzLnVwZGF0ZVByb2dyZXNzKCdcdUQ4M0RcdURDQzQgRXh0cmFjdGluZyBtYXJrZG93biBjb250ZW50Li4uJywgMzApO1xuICAgICAgY29uc3QgZXh0cmFjdG9yID0gbmV3IE1hcmtkb3duRXh0cmFjdG9yKHRoaXMuYXBwLCB0aGlzLmFwcC52YXVsdCk7XG4gICAgICBjb25zdCBleHRyYWN0ZWQgPSBhd2FpdCBleHRyYWN0b3IuZXh0cmFjdE1hcmtkb3duKHRoaXMuZmlsZSk7XG5cbiAgICAgIGNvbnNvbGUubG9nKGBcdUQ4M0RcdURDQ0EgRXh0cmFjdGVkOiAke2V4dHJhY3RlZC5pbWFnZXMubGVuZ3RofSBpbWFnZXMsICR7ZXh0cmFjdGVkLmludGVybmFsTGlua3MubGVuZ3RofSBpbnRlcm5hbCBsaW5rc2ApO1xuXG4gICAgICAvLyBMb2cgZXh0cmFjdGVkIGltYWdlIGRldGFpbHNcbiAgICAgIGlmIChleHRyYWN0ZWQuaW1hZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1x1RDgzRFx1RENGNyBJbWFnZSBkZXRhaWxzOicpO1xuICAgICAgICBleHRyYWN0ZWQuaW1hZ2VzLmZvckVhY2goKGltZywgaWR4KSA9PiB7XG4gICAgICAgICAgY29uc29sZS5sb2coYCAgJHtpZHggKyAxfS4gJHtpbWcubmFtZX0gKCR7KGltZy5zaXplIC8gMTAyNCkudG9GaXhlZCgxKX1LQiwgJHtpbWcubWltZVR5cGV9KWApO1xuICAgICAgICAgIGNvbnNvbGUubG9nKGAgICAgIE9yaWdpbmFsIHBhdGg6ICR7aW1nLm9yaWdpbmFsUGF0aH1gKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0ZXAgMzogQ3JlYXRlIG1lbW8gKDUwJSlcbiAgICAgIHRoaXMudXBkYXRlUHJvZ3Jlc3MoJ1x1RDgzRFx1RENERCBDcmVhdGluZyBtZW1vLi4uJywgNTApO1xuICAgICAgY29uc3QgbWVtb1VwbG9hZGVyID0gbmV3IE1lbW9VcGxvYWRlcigpO1xuICAgICAgY29uc3QgeyBtZW1vSWQgfSA9IGF3YWl0IG1lbW9VcGxvYWRlci5jcmVhdGVNZW1vKHNob3J0Q29kZSwgcGFzc3dvcmQpO1xuXG4gICAgICAvLyBTdGVwIDQ6IFVwbG9hZCBpbWFnZXMgKDcwJSlcbiAgICAgIGxldCB1cGRhdGVkQ29udGVudCA9IGV4dHJhY3RlZC5jb250ZW50O1xuICAgICAgaWYgKGV4dHJhY3RlZC5pbWFnZXMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLnVwZGF0ZVByb2dyZXNzKGBcdUQ4M0RcdURDRTQgVXBsb2FkaW5nICR7ZXh0cmFjdGVkLmltYWdlcy5sZW5ndGh9IGltYWdlKHMpLi4uYCwgNzApO1xuXG4gICAgICAgIC8vIFZlcmlmeSBhdXRoZW50aWNhdGlvbiBiZWZvcmUgdXBsb2FkaW5nIGltYWdlc1xuICAgICAgICBjb25zb2xlLmxvZygnXHVEODNEXHVERDExIFVzZXIgYXV0aGVudGljYXRlZDonLCB0aGlzLmF1dGhNYW5hZ2VyLmlzQXV0aGVudGljYXRlZCgpKTtcbiAgICAgICAgY29uc29sZS5sb2coJ1x1RDgzRFx1REM2NCBDdXJyZW50IHVzZXI6JywgdGhpcy5hdXRoTWFuYWdlci5nZXRDdXJyZW50VXNlckVtYWlsKCkpO1xuXG4gICAgICAgIGNvbnN0IGltYWdlVXBsb2FkZXIgPSBuZXcgSW1hZ2VVcGxvYWRlcigpO1xuICAgICAgICBjb25zdCB1cGxvYWRlZEltYWdlcyA9IGF3YWl0IGltYWdlVXBsb2FkZXIudXBsb2FkSW1hZ2VzKGV4dHJhY3RlZC5pbWFnZXMsIG1lbW9JZCk7XG5cbiAgICAgICAgLy8gUmVwbGFjZSBpbWFnZSBwYXRocyBpbiBjb250ZW50XG4gICAgICAgIHVwZGF0ZWRDb250ZW50ID0gaW1hZ2VVcGxvYWRlci5yZXBsYWNlSW1hZ2VQYXRocyhcbiAgICAgICAgICBleHRyYWN0ZWQuY29udGVudCxcbiAgICAgICAgICBleHRyYWN0ZWQuaW1hZ2VzLFxuICAgICAgICAgIHVwbG9hZGVkSW1hZ2VzXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0ZXAgNTogU2F2ZSBtZW1vICg5MCUpXG4gICAgICB0aGlzLnVwZGF0ZVByb2dyZXNzKCdcdUQ4M0RcdURDQkUgU2F2aW5nIG1lbW8uLi4nLCA5MCk7XG4gICAgICBhd2FpdCBtZW1vVXBsb2FkZXIuc2F2ZU1lbW8oXG4gICAgICAgIG1lbW9JZCxcbiAgICAgICAgc2hvcnRDb2RlLFxuICAgICAgICB1cGRhdGVkQ29udGVudCxcbiAgICAgICAgZXh0cmFjdGVkLmltYWdlcy5sZW5ndGggPiAwID8gW10gOiBbXSwgLy8gSW1hZ2VzIGFyZSBhbHJlYWR5IGluIGNvbnRlbnQgYXMgVVJMc1xuICAgICAgICBleHRyYWN0ZWQuaW50ZXJuYWxMaW5rcyxcbiAgICAgICAgMCxcbiAgICAgICAgcGFzc3dvcmRcbiAgICAgICk7XG5cbiAgICAgIC8vIENvbXBsZXRlICgxMDAlKVxuICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcygnXHUyNzA1IFVwbG9hZCBjb21wbGV0ZSEnLCAxMDApO1xuXG4gICAgICAvLyBTYXZlIFVSTCB0byBtZW1vcnkgY2FjaGVcbiAgICAgIGNvbnN0IGRpc3BsYXlVcmwgPSBgaHR0cHM6Ly91dXUuZ2wvJHtzaG9ydENvZGV9YDtcbiAgICAgIHRoaXMucGx1Z2luLnNldFV1dWdsVXJsKHRoaXMuZmlsZSwgZGlzcGxheVVybCk7XG5cbiAgICAgIC8vIFNhdmUgdG8gcGVyc2lzdGVudCBzdG9yYWdlIChJTVBPUlRBTlQ6IHN1cnZpdmVzIHBsdWdpbiByZXN0YXJ0KVxuICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVVybENhY2hlKCk7XG5cbiAgICAgIC8vIFVwZGF0ZSBzdGF0dXMgYmFyIChETyBOT1QgdXBkYXRlIGZyb250bWF0dGVyIC0gdXNlcidzIGNvbnRlbnQgbXVzdCBub3QgYmUgbW9kaWZpZWQpXG4gICAgICAvLyBAdHMtaWdub3JlIC0gdXBkYXRlU3RhdHVzQmFyIGlzIGEgcHVibGljIG1ldGhvZFxuICAgICAgYXdhaXQgdGhpcy5wbHVnaW4udXBkYXRlU3RhdHVzQmFyKCk7XG5cbiAgICAgIC8vIFNob3cgc3VjY2Vzc1xuICAgICAgdGhpcy5zaG93U3VjY2VzcyhkaXNwbGF5VXJsLCAnTm90ZSB1cGxvYWRlZCBzdWNjZXNzZnVsbHkhJyk7XG5cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcdTI3NEMgVXBsb2FkIGZhaWxlZDonLCBlcnJvcik7XG4gICAgICB0aGlzLnNob3dFcnJvcihlcnJvci5tZXNzYWdlIHx8ICdVcGxvYWQgZmFpbGVkJyk7XG4gICAgICBpZiAodGhpcy5tYWluQ29udGVudCkgdGhpcy5tYWluQ29udGVudC5zaG93KCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVQcm9ncmVzcyhtZXNzYWdlOiBzdHJpbmcsIHBlcmNlbnRhZ2U/OiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5wcm9ncmVzc1RleHQpIHtcbiAgICAgIHRoaXMucHJvZ3Jlc3NUZXh0LnNldFRleHQobWVzc2FnZSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnByb2dyZXNzQmFyICYmIHBlcmNlbnRhZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5wcm9ncmVzc0Jhci5zdHlsZS53aWR0aCA9IGAke3BlcmNlbnRhZ2V9JWA7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzaG93U3VjY2Vzcyh1cmw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nID0gJ1VwbG9hZCBzdWNjZXNzZnVsIScpIHtcbiAgICBpZiAoIXRoaXMucmVzdWx0RWwpIHJldHVybjtcblxuICAgIHRoaXMucHJvZ3Jlc3NFbD8uaGlkZSgpO1xuICAgIHRoaXMucmVzdWx0RWwuZW1wdHkoKTtcbiAgICB0aGlzLnJlc3VsdEVsLnNob3coKTtcbiAgICB0aGlzLnJlc3VsdEVsLmFkZENsYXNzKCd1dXVnbC1zdWNjZXNzLWNvbnRhaW5lcicpO1xuXG4gICAgLy8gU3VjY2VzcyBpY29uIGFuZCBtZXNzYWdlXG4gICAgY29uc3Qgc3VjY2Vzc0hlYWRlciA9IHRoaXMucmVzdWx0RWwuY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtc3VjY2Vzcy1oZWFkZXInIH0pO1xuICAgIHN1Y2Nlc3NIZWFkZXIuY3JlYXRlRWwoJ2RpdicsIHtcbiAgICAgIHRleHQ6IGBcdTI3MDUgJHttZXNzYWdlfWAsXG4gICAgICBjbHM6ICd1dXVnbC1zdWNjZXNzLXRpdGxlJyxcbiAgICB9KTtcblxuICAgIC8vIFVSTCBkaXNwbGF5XG4gICAgY29uc3QgdXJsU2VjdGlvbiA9IHRoaXMucmVzdWx0RWwuY3JlYXRlRGl2KHsgY2xzOiAndXV1Z2wtc3VjY2Vzcy11cmwtc2VjdGlvbicgfSk7XG4gICAgdXJsU2VjdGlvbi5jcmVhdGVFbCgncCcsIHtcbiAgICAgIHRleHQ6ICdZb3VyIG5vdGUgaXMgbm93IGxpdmUgYXQ6JyxcbiAgICAgIGNsczogJ3V1dWdsLXN1Y2Nlc3MtbGFiZWwnXG4gICAgfSk7XG5cbiAgICBjb25zdCBsaW5rID0gdXJsU2VjdGlvbi5jcmVhdGVFbCgnYScsIHtcbiAgICAgIHRleHQ6IHVybCxcbiAgICAgIGhyZWY6IHVybCxcbiAgICAgIGNsczogJ3V1dWdsLXN1Y2Nlc3MtdXJsJ1xuICAgIH0pO1xuICAgIGxpbmsuc2V0QXR0cmlidXRlKCd0YXJnZXQnLCAnX2JsYW5rJyk7XG5cbiAgICAvLyBCdXR0b24gY29udGFpbmVyXG4gICAgY29uc3QgYnV0dG9uQ29udGFpbmVyID0gdGhpcy5yZXN1bHRFbC5jcmVhdGVEaXYoeyBjbHM6ICd1dXVnbC1zdWNjZXNzLWJ1dHRvbnMnIH0pO1xuXG4gICAgLy8gQ29weSBMaW5rIGJ1dHRvbiAocHJpbWFyeSlcbiAgICBjb25zdCBjb3B5QnV0dG9uID0gYnV0dG9uQ29udGFpbmVyLmNyZWF0ZUVsKCdidXR0b24nLCB7XG4gICAgICB0ZXh0OiAnQ29weSBMaW5rJyxcbiAgICAgIGNsczogJ3V1dWdsLWJ0biB1dXVnbC1idG4tcHJpbWFyeScsXG4gICAgfSk7XG4gICAgY29weUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcbiAgICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHVybCk7XG4gICAgICBuZXcgTm90aWNlKCdMaW5rIGNvcGllZCB0byBjbGlwYm9hcmQhJyk7XG4gICAgfSk7XG5cbiAgICAvLyBDbG9zZSBidXR0b24gKHNlY29uZGFyeSlcbiAgICBjb25zdCBjbG9zZUJ1dHRvbiA9IGJ1dHRvbkNvbnRhaW5lci5jcmVhdGVFbCgnYnV0dG9uJywge1xuICAgICAgdGV4dDogJ0Nsb3NlJyxcbiAgICAgIGNsczogJ3V1dWdsLWJ0biB1dXVnbC1idG4tc2Vjb25kYXJ5JyxcbiAgICB9KTtcbiAgICBjbG9zZUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHRoaXMuY2xvc2UoKSk7XG5cbiAgICBuZXcgTm90aWNlKGBcdTI3MDUgJHttZXNzYWdlfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG93RXJyb3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLnJlc3VsdEVsKSByZXR1cm47XG5cbiAgICB0aGlzLnByb2dyZXNzRWw/LmhpZGUoKTtcbiAgICBpZiAodGhpcy5tYWluQ29udGVudCkgdGhpcy5tYWluQ29udGVudC5oaWRlKCk7IC8vIEhpZGUgbWFpbiBjb250ZW50IHdoZW4gc2hvd2luZyBlcnJvclxuICAgIHRoaXMucmVzdWx0RWwuZW1wdHkoKTtcbiAgICB0aGlzLnJlc3VsdEVsLnNob3coKTtcblxuICAgIHRoaXMucmVzdWx0RWwuY3JlYXRlRWwoJ2RpdicsIHtcbiAgICAgIHRleHQ6IGBcdTI3NEMgRmFpbGVkOiAke21lc3NhZ2V9YCxcbiAgICAgIGNsczogJ3VwbG9hZC1tb2RhbC1lcnJvcicsXG4gICAgfSk7XG5cbiAgICBjb25zdCBjbG9zZUJ1dHRvbiA9IHRoaXMucmVzdWx0RWwuY3JlYXRlRWwoJ2J1dHRvbicsIHtcbiAgICAgIHRleHQ6ICdDbG9zZScsXG4gICAgfSk7XG4gICAgY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB0aGlzLmNsb3NlKCkpO1xuXG4gICAgbmV3IE5vdGljZShgXHUyNzRDIEZhaWxlZDogJHttZXNzYWdlfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBzYW5pdGl6ZVNob3J0Q29kZShuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuYW1lXG4gICAgICAudG9Mb3dlckNhc2UoKVxuICAgICAgLnJlcGxhY2UoL1teYS16QS1aMC05XHVBQzAwLVx1RDdBMy1dL2csICctJylcbiAgICAgIC5yZXBsYWNlKC8tKy9nLCAnLScpXG4gICAgICAucmVwbGFjZSgvXi18LSQvZywgJycpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZVJhbmRvbVNob3J0Q29kZSgpOiBzdHJpbmcge1xuICAgIC8vIEdlbmVyYXRlIHJhbmRvbSA4LWNoYXJhY3RlciBhbHBoYW51bWVyaWMgY29kZVxuICAgIGNvbnN0IGNoYXJzID0gJ2FiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSc7XG4gICAgbGV0IHJlc3VsdCA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgODsgaSsrKSB7XG4gICAgICByZXN1bHQgKz0gY2hhcnMuY2hhckF0KE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGNoYXJzLmxlbmd0aCkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbn1cbiIsICIvKipcbiAqIE1hcmtkb3duIEV4dHJhY3RvclxuICogRXh0cmFjdHMgbWFya2Rvd24gY29udGVudCwgaW50ZXJuYWwgbGlua3MsIGFuZCBpbWFnZXMgZnJvbSBPYnNpZGlhbiBmaWxlc1xuICovXG5cbmltcG9ydCB7IFRGaWxlLCBWYXVsdCwgQXBwIH0gZnJvbSAnb2JzaWRpYW4nO1xuXG5leHBvcnQgaW50ZXJmYWNlIE1hcmtkb3duSW1hZ2Uge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRhdGE6IEFycmF5QnVmZmVyO1xuICBtaW1lVHlwZTogc3RyaW5nO1xuICBzaXplOiBudW1iZXI7XG4gIGFsdFRleHQ/OiBzdHJpbmc7XG4gIG9yaWdpbmFsUGF0aDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4dHJhY3RlZE1hcmtkb3duIHtcbiAgY29udGVudDogc3RyaW5nO1xuICBpbWFnZXM6IE1hcmtkb3duSW1hZ2VbXTtcbiAgaW50ZXJuYWxMaW5rczogc3RyaW5nW107XG59XG5cbmV4cG9ydCBjbGFzcyBNYXJrZG93bkV4dHJhY3RvciB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBwOiBBcHAsIHByaXZhdGUgdmF1bHQ6IFZhdWx0KSB7fVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0IG1hcmtkb3duIGNvbnRlbnQsIGltYWdlcywgYW5kIGludGVybmFsIGxpbmtzIGZyb20gYSBmaWxlXG4gICAqL1xuICBhc3luYyBleHRyYWN0TWFya2Rvd24oZmlsZTogVEZpbGUpOiBQcm9taXNlPEV4dHJhY3RlZE1hcmtkb3duPiB7XG4gICAgLy8gMS4gUmVhZCBtYXJrZG93biBjb250ZW50XG4gICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMudmF1bHQucmVhZChmaWxlKTtcblxuICAgIC8vIDIuIEV4dHJhY3QgaW50ZXJuYWwgbGlua3MgW1tsaW5rXV1cbiAgICBjb25zdCBpbnRlcm5hbExpbmtzID0gdGhpcy5leHRyYWN0SW50ZXJuYWxMaW5rcyhjb250ZW50KTtcblxuICAgIC8vIDMuIEV4dHJhY3QgYW5kIHJlYWQgaW1hZ2VzXG4gICAgY29uc3QgaW1hZ2VzID0gYXdhaXQgdGhpcy5leHRyYWN0SW1hZ2VzKGNvbnRlbnQsIGZpbGUpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQsXG4gICAgICBpbWFnZXMsXG4gICAgICBpbnRlcm5hbExpbmtzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdCBpbnRlcm5hbCBsaW5rcyBmcm9tIG1hcmtkb3duIGNvbnRlbnRcbiAgICogTWF0Y2hlcyBbW2xpbmtdXSBhbmQgW1tkaXNwbGF5fGxpbmtdXSBwYXR0ZXJuc1xuICAgKi9cbiAgcHJpdmF0ZSBleHRyYWN0SW50ZXJuYWxMaW5rcyhjb250ZW50OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgcmVnZXggPSAvXFxbXFxbKFteXFxdXSspXFxdXFxdL2c7XG4gICAgY29uc3QgbGlua3M6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IG1hdGNoO1xuXG4gICAgd2hpbGUgKChtYXRjaCA9IHJlZ2V4LmV4ZWMoY29udGVudCkpICE9PSBudWxsKSB7XG4gICAgICAvLyBTa2lwIGltYWdlIGxpbmtzICghW1tpbWFnZV1dKVxuICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IG1hdGNoLmluZGV4O1xuICAgICAgaWYgKHN0YXJ0SW5kZXggPiAwICYmIGNvbnRlbnRbc3RhcnRJbmRleCAtIDFdID09PSAnIScpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIEV4dHJhY3QgbGluayAoaGFuZGxlIFtbZGlzcGxheXx0YXJnZXRdXSBmb3JtYXQpXG4gICAgICBjb25zdCBsaW5rVGV4dCA9IG1hdGNoWzFdO1xuICAgICAgY29uc3QgcGFydHMgPSBsaW5rVGV4dC5zcGxpdCgnfCcpO1xuICAgICAgY29uc3QgdGFyZ2V0ID0gcGFydHMubGVuZ3RoID4gMSA/IHBhcnRzWzFdLnRyaW0oKSA6IHBhcnRzWzBdLnRyaW0oKTtcblxuICAgICAgbGlua3MucHVzaCh0YXJnZXQpO1xuICAgIH1cblxuICAgIC8vIFJlbW92ZSBkdXBsaWNhdGVzXG4gICAgcmV0dXJuIFsuLi5uZXcgU2V0KGxpbmtzKV07XG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdCBhbmQgcmVhZCBpbWFnZSBmaWxlcyBmcm9tIG1hcmtkb3duIGNvbnRlbnRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZXh0cmFjdEltYWdlcyhjb250ZW50OiBzdHJpbmcsIHNvdXJjZUZpbGU6IFRGaWxlKTogUHJvbWlzZTxNYXJrZG93bkltYWdlW10+IHtcbiAgICBjb25zdCBpbWFnZXM6IE1hcmtkb3duSW1hZ2VbXSA9IFtdO1xuXG4gICAgLy8gTWF0Y2ggYm90aCAhW10ocGF0aCkgYW5kICFbW3dpa2lsaW5rXV0gZm9ybWF0c1xuICAgIGNvbnN0IGltYWdlUmVnZXggPSAvIVxcWyhbXlxcXV0qKVxcXVxcKChbXildKylcXCl8IVxcW1xcWyhbXlxcXV0rKVxcXVxcXS9nO1xuICAgIGxldCBtYXRjaDtcblxuICAgIHdoaWxlICgobWF0Y2ggPSBpbWFnZVJlZ2V4LmV4ZWMoY29udGVudCkpICE9PSBudWxsKSB7XG4gICAgICBsZXQgYWx0VGV4dDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgbGV0IGltYWdlUGF0aDogc3RyaW5nO1xuXG4gICAgICBpZiAobWF0Y2hbMl0pIHtcbiAgICAgICAgLy8gU3RhbmRhcmQgbWFya2Rvd246ICFbYWx0XShwYXRoKVxuICAgICAgICBhbHRUZXh0ID0gbWF0Y2hbMV0gfHwgdW5kZWZpbmVkO1xuICAgICAgICBpbWFnZVBhdGggPSBtYXRjaFsyXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdpa2ktc3R5bGU6ICFbW2ltYWdlXV1cbiAgICAgICAgaW1hZ2VQYXRoID0gbWF0Y2hbM107XG4gICAgICAgIGFsdFRleHQgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFJlc29sdmUgaW1hZ2UgcGF0aCByZWxhdGl2ZSB0byBzb3VyY2UgZmlsZVxuICAgICAgICBjb25zdCBpbWFnZUZpbGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpcnN0TGlua3BhdGhEZXN0KFxuICAgICAgICAgIGltYWdlUGF0aCxcbiAgICAgICAgICBzb3VyY2VGaWxlLnBhdGhcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWltYWdlRmlsZSkge1xuICAgICAgICAgIGNvbnNvbGUud2FybihgXHUyNkEwXHVGRTBGIEltYWdlIG5vdCBmb3VuZCBpbiB2YXVsdDogJHtpbWFnZVBhdGh9YCk7XG4gICAgICAgICAgY29uc29sZS53YXJuKGBTb3VyY2UgZmlsZSBwYXRoOiAke3NvdXJjZUZpbGUucGF0aH1gKTtcbiAgICAgICAgICBjb25zb2xlLndhcm4oYExvb2tpbmcgZm9yOiAke2ltYWdlUGF0aH1gKTtcbiAgICAgICAgICAvLyBTa2lwIHRoaXMgaW1hZ2UgYnV0IGNvbnRpbnVlIHdpdGggb3RoZXJzXG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWFkIGltYWdlIGRhdGFcbiAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMudmF1bHQucmVhZEJpbmFyeShpbWFnZUZpbGUpO1xuICAgICAgICBjb25zdCBtaW1lVHlwZSA9IHRoaXMuZ2V0TWltZVR5cGUoaW1hZ2VGaWxlLmV4dGVuc2lvbik7XG5cbiAgICAgICAgaW1hZ2VzLnB1c2goe1xuICAgICAgICAgIG5hbWU6IGltYWdlRmlsZS5uYW1lLFxuICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgbWltZVR5cGUsXG4gICAgICAgICAgc2l6ZTogZGF0YS5ieXRlTGVuZ3RoLFxuICAgICAgICAgIGFsdFRleHQsXG4gICAgICAgICAgb3JpZ2luYWxQYXRoOiBpbWFnZVBhdGgsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKGBcdUQ4M0RcdURDRjcgRXh0cmFjdGVkIGltYWdlOiAke2ltYWdlRmlsZS5uYW1lfSAoJHsoZGF0YS5ieXRlTGVuZ3RoIC8gMTAyNCkudG9GaXhlZCgxKX1LQilgKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYFx1Mjc0QyBGYWlsZWQgdG8gcmVhZCBpbWFnZTogJHtpbWFnZVBhdGh9YCwgZXJyb3IpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbWFnZXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IE1JTUUgdHlwZSBmcm9tIGZpbGUgZXh0ZW5zaW9uXG4gICAqL1xuICBwcml2YXRlIGdldE1pbWVUeXBlKGV4dGVuc2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBtaW1lVHlwZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAncG5nJzogJ2ltYWdlL3BuZycsXG4gICAgICAnanBnJzogJ2ltYWdlL2pwZWcnLFxuICAgICAgJ2pwZWcnOiAnaW1hZ2UvanBlZycsXG4gICAgICAnZ2lmJzogJ2ltYWdlL2dpZicsXG4gICAgICAnc3ZnJzogJ2ltYWdlL3N2Zyt4bWwnLFxuICAgICAgJ3dlYnAnOiAnaW1hZ2Uvd2VicCcsXG4gICAgICAnYm1wJzogJ2ltYWdlL2JtcCcsXG4gICAgfTtcblxuICAgIHJldHVybiBtaW1lVHlwZXNbZXh0ZW5zaW9uLnRvTG93ZXJDYXNlKCldIHx8ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nO1xuICB9XG59XG4iLCAiLyoqXG4gKiBJbWFnZSBVcGxvYWRlclxuICogVXBsb2FkcyBpbWFnZXMgdG8gRmlyZWJhc2UgU3RvcmFnZVxuICovXG5cbmltcG9ydCB7IHN0b3JhZ2UgfSBmcm9tICcuL2ZpcmViYXNlLWNvbmZpZyc7XG5pbXBvcnQgeyByZWYsIHVwbG9hZEJ5dGVzLCBnZXREb3dubG9hZFVSTCB9IGZyb20gJ2ZpcmViYXNlL3N0b3JhZ2UnO1xuaW1wb3J0IHsgTWFya2Rvd25JbWFnZSB9IGZyb20gJy4vbWFya2Rvd24tZXh0cmFjdG9yJztcblxuZXhwb3J0IGludGVyZmFjZSBVcGxvYWRlZEltYWdlIHtcbiAgb3JpZ2luYWxOYW1lOiBzdHJpbmc7XG4gIHN0b3JhZ2VQYXRoOiBzdHJpbmc7XG4gIGRvd25sb2FkVXJsOiBzdHJpbmc7XG4gIG1pbWVUeXBlOiBzdHJpbmc7XG4gIHNpemU6IG51bWJlcjtcbiAgYWx0VGV4dD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIEltYWdlVXBsb2FkZXIge1xuICAvKipcbiAgICogVXBsb2FkIGltYWdlcyB0byBGaXJlYmFzZSBTdG9yYWdlXG4gICAqIEBwYXJhbSBpbWFnZXMgQXJyYXkgb2YgaW1hZ2VzIHRvIHVwbG9hZFxuICAgKiBAcGFyYW0gbWVtb0lkIE1lbW8gSUQgZm9yIHN0b3JhZ2UgcGF0aFxuICAgKiBAcmV0dXJucyBBcnJheSBvZiB1cGxvYWRlZCBpbWFnZSBtZXRhZGF0YVxuICAgKi9cbiAgYXN5bmMgdXBsb2FkSW1hZ2VzKGltYWdlczogTWFya2Rvd25JbWFnZVtdLCBtZW1vSWQ6IHN0cmluZyk6IFByb21pc2U8VXBsb2FkZWRJbWFnZVtdPiB7XG4gICAgY29uc3QgdXBsb2FkZWRJbWFnZXM6IFVwbG9hZGVkSW1hZ2VbXSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbWFnZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGltYWdlID0gaW1hZ2VzW2ldO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc29sZS5sb2coYFx1RDgzRFx1RENFNCBVcGxvYWRpbmcgaW1hZ2UgJHtpICsgMX0vJHtpbWFnZXMubGVuZ3RofTogJHtpbWFnZS5uYW1lfS4uLmApO1xuICAgICAgICBjb25zb2xlLmxvZyhgICAgU2l6ZTogJHsoaW1hZ2Uuc2l6ZSAvIDEwMjQpLnRvRml4ZWQoMSl9S0JgKTtcbiAgICAgICAgY29uc29sZS5sb2coYCAgIFR5cGU6ICR7aW1hZ2UubWltZVR5cGV9YCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHN0b3JhZ2UgcGF0aDogbWVtb3Mve21lbW9JZH0vaW1hZ2VzL3tpbWFnZU5hbWV9XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHNhbml0aXplZE5hbWUgPSB0aGlzLnNhbml0aXplRmlsZU5hbWUoaW1hZ2UubmFtZSk7XG4gICAgICAgIGNvbnN0IHN0b3JhZ2VQYXRoID0gYG1lbW9zLyR7bWVtb0lkfS9pbWFnZXMvJHt0aW1lc3RhbXB9XyR7c2FuaXRpemVkTmFtZX1gO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKGAgICBTdG9yYWdlIHBhdGg6ICR7c3RvcmFnZVBhdGh9YCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHN0b3JhZ2UgcmVmZXJlbmNlXG4gICAgICAgIGNvbnN0IHN0b3JhZ2VSZWYgPSByZWYoc3RvcmFnZSwgc3RvcmFnZVBhdGgpO1xuXG4gICAgICAgIC8vIENvbnZlcnQgQXJyYXlCdWZmZXIgdG8gQmxvYlxuICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2ltYWdlLmRhdGFdLCB7IHR5cGU6IGltYWdlLm1pbWVUeXBlIH0pO1xuICAgICAgICBjb25zb2xlLmxvZyhgICAgQmxvYiBjcmVhdGVkOiAke2Jsb2Iuc2l6ZX0gYnl0ZXNgKTtcblxuICAgICAgICAvLyBVcGxvYWQgdG8gRmlyZWJhc2UgU3RvcmFnZVxuICAgICAgICBjb25zb2xlLmxvZyhgICAgU3RhcnRpbmcgdXBsb2FkLi4uYCk7XG4gICAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgdXBsb2FkQnl0ZXMoc3RvcmFnZVJlZiwgYmxvYiwge1xuICAgICAgICAgIGNvbnRlbnRUeXBlOiBpbWFnZS5taW1lVHlwZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gR2V0IGRvd25sb2FkIFVSTFxuICAgICAgICBjb25zdCBkb3dubG9hZFVybCA9IGF3YWl0IGdldERvd25sb2FkVVJMKHNuYXBzaG90LnJlZik7XG4gICAgICAgIGNvbnNvbGUubG9nKGAgICBEb3dubG9hZCBVUkw6ICR7ZG93bmxvYWRVcmx9YCk7XG5cbiAgICAgICAgdXBsb2FkZWRJbWFnZXMucHVzaCh7XG4gICAgICAgICAgb3JpZ2luYWxOYW1lOiBpbWFnZS5uYW1lLFxuICAgICAgICAgIHN0b3JhZ2VQYXRoOiBzbmFwc2hvdC5yZWYuZnVsbFBhdGgsXG4gICAgICAgICAgZG93bmxvYWRVcmwsXG4gICAgICAgICAgbWltZVR5cGU6IGltYWdlLm1pbWVUeXBlLFxuICAgICAgICAgIHNpemU6IGltYWdlLnNpemUsXG4gICAgICAgICAgYWx0VGV4dDogaW1hZ2UuYWx0VGV4dCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc29sZS5sb2coYFx1MjcwNSBJbWFnZSB1cGxvYWRlZCBzdWNjZXNzZnVsbHk6ICR7aW1hZ2UubmFtZX1gKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgXHUyNzRDIEZhaWxlZCB0byB1cGxvYWQgaW1hZ2U6ICR7aW1hZ2UubmFtZX1gLCBlcnJvcik7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGNvZGU6JywgZXJyb3IuY29kZSk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIG1lc3NhZ2U6JywgZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Z1bGwgZXJyb3I6JywgSlNPTi5zdHJpbmdpZnkoZXJyb3IsIG51bGwsIDIpKTtcblxuICAgICAgICAvLyBSZS10aHJvdyB0aGUgZXJyb3Igd2l0aCBtb3JlIGRldGFpbHNcbiAgICAgICAgY29uc3QgZXJyb3JNc2cgPSBlcnJvci5jb2RlID09PSAnc3RvcmFnZS91bmF1dGhvcml6ZWQnXG4gICAgICAgICAgPyAnU3RvcmFnZSBwZXJtaXNzaW9uIGRlbmllZC4gUGxlYXNlIGNoZWNrIEZpcmViYXNlIFN0b3JhZ2UgcnVsZXMuJ1xuICAgICAgICAgIDogZXJyb3IubWVzc2FnZSB8fCBlcnJvci5jb2RlIHx8ICdVbmtub3duIGVycm9yJztcblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byB1cGxvYWQgaW1hZ2U6ICR7aW1hZ2UubmFtZX1cXG4ke2Vycm9yTXNnfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB1cGxvYWRlZEltYWdlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTYW5pdGl6ZSBmaWxlIG5hbWUgZm9yIHN0b3JhZ2VcbiAgICovXG4gIHByaXZhdGUgc2FuaXRpemVGaWxlTmFtZShmaWxlTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBSZW1vdmUgc3BlY2lhbCBjaGFyYWN0ZXJzIGFuZCBzcGFjZXNcbiAgICByZXR1cm4gZmlsZU5hbWVcbiAgICAgIC5yZXBsYWNlKC9bXmEtekEtWjAtOS5fLV0vZywgJ18nKVxuICAgICAgLnJlcGxhY2UoL197Mix9L2csICdfJylcbiAgICAgIC50b0xvd2VyQ2FzZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2UgaW1hZ2UgcGF0aHMgaW4gbWFya2Rvd24gY29udGVudCB3aXRoIHVwbG9hZGVkIFVSTHNcbiAgICovXG4gIHJlcGxhY2VJbWFnZVBhdGhzKFxuICAgIGNvbnRlbnQ6IHN0cmluZyxcbiAgICBvcmlnaW5hbEltYWdlczogTWFya2Rvd25JbWFnZVtdLFxuICAgIHVwbG9hZGVkSW1hZ2VzOiBVcGxvYWRlZEltYWdlW11cbiAgKTogc3RyaW5nIHtcbiAgICBsZXQgdXBkYXRlZENvbnRlbnQgPSBjb250ZW50O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcmlnaW5hbEltYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgb3JpZ2luYWwgPSBvcmlnaW5hbEltYWdlc1tpXTtcbiAgICAgIGNvbnN0IHVwbG9hZGVkID0gdXBsb2FkZWRJbWFnZXNbaV07XG5cbiAgICAgIGlmICghdXBsb2FkZWQpIGNvbnRpbnVlO1xuXG4gICAgICAvLyBSZXBsYWNlICFbW3dpa2lsaW5rXV0gZm9ybWF0XG4gICAgICBjb25zdCB3aWtpUmVnZXggPSBuZXcgUmVnRXhwKGAhXFxcXFtcXFxcWyR7dGhpcy5lc2NhcGVSZWdleChvcmlnaW5hbC5vcmlnaW5hbFBhdGgpfVxcXFxdXFxcXF1gLCAnZycpO1xuICAgICAgdXBkYXRlZENvbnRlbnQgPSB1cGRhdGVkQ29udGVudC5yZXBsYWNlKFxuICAgICAgICB3aWtpUmVnZXgsXG4gICAgICAgIGAhWyR7dXBsb2FkZWQuYWx0VGV4dCB8fCB1cGxvYWRlZC5vcmlnaW5hbE5hbWV9XSgke3VwbG9hZGVkLmRvd25sb2FkVXJsfSlgXG4gICAgICApO1xuXG4gICAgICAvLyBSZXBsYWNlICFbXShwYXRoKSBmb3JtYXRcbiAgICAgIGNvbnN0IG1kUmVnZXggPSBuZXcgUmVnRXhwKGAhXFxcXFsoW15cXFxcXV0qKVxcXFxdXFxcXCgke3RoaXMuZXNjYXBlUmVnZXgob3JpZ2luYWwub3JpZ2luYWxQYXRoKX1cXFxcKWAsICdnJyk7XG4gICAgICB1cGRhdGVkQ29udGVudCA9IHVwZGF0ZWRDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIG1kUmVnZXgsXG4gICAgICAgIGAhWyQxXSgke3VwbG9hZGVkLmRvd25sb2FkVXJsfSlgXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB1cGRhdGVkQ29udGVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFc2NhcGUgc3BlY2lhbCByZWdleCBjaGFyYWN0ZXJzXG4gICAqL1xuICBwcml2YXRlIGVzY2FwZVJlZ2V4KHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gc3RyLnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCAnXFxcXCQmJyk7XG4gIH1cbn1cbiIsICIvKipcbiAqIE1lbW8gVXBsb2FkZXJcbiAqIEhhbmRsZXMgY3JlYXRpbmcgYW5kIHNhdmluZyBtZW1vcyB2aWEgRmlyZWJhc2UgRnVuY3Rpb25zXG4gKi9cblxuaW1wb3J0IHsgZnVuY3Rpb25zIH0gZnJvbSAnLi9maXJlYmFzZS1jb25maWcnO1xuaW1wb3J0IHsgaHR0cHNDYWxsYWJsZSB9IGZyb20gJ2ZpcmViYXNlL2Z1bmN0aW9ucyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlTWVtb1JlcXVlc3Qge1xuICBzaG9ydENvZGU/OiBzdHJpbmc7XG4gIGlzUHVibGljPzogYm9vbGVhbjtcbiAgcGFzc3dvcmQ/OiBzdHJpbmc7XG4gIGNvbnRlbnRUeXBlOiAnbWFya2Rvd24nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNhdmVNZW1vUmVxdWVzdCB7XG4gIHNob3J0Q29kZT86IHN0cmluZztcbiAgbWVtb0lkOiBzdHJpbmc7XG4gIG1hcmtkb3duRGF0YToge1xuICAgIGNvbnRlbnQ6IHN0cmluZztcbiAgICBpbWFnZXM6IEFycmF5PHtcbiAgICAgIGlkOiBzdHJpbmc7XG4gICAgICBzdG9yYWdlUGF0aDogc3RyaW5nO1xuICAgICAgb3JpZ2luYWxOYW1lOiBzdHJpbmc7XG4gICAgICBtaW1lVHlwZTogc3RyaW5nO1xuICAgICAgc2l6ZTogbnVtYmVyO1xuICAgICAgYWx0VGV4dD86IHN0cmluZztcbiAgICB9PjtcbiAgICBpbnRlcm5hbExpbmtzOiBzdHJpbmdbXTtcbiAgfTtcbiAgdmVyc2lvbj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZW1vVXBsb2FkUmVzdWx0IHtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgbWVtb0lkOiBzdHJpbmc7XG4gIHNob3J0Q29kZTogc3RyaW5nO1xuICB1cmw6IHN0cmluZztcbiAgdmVyc2lvbjogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgTWVtb1VwbG9hZGVyIHtcbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBNYXJrZG93biBtZW1vXG4gICAqL1xuICBhc3luYyBjcmVhdGVNZW1vKHNob3J0Q29kZTogc3RyaW5nLCBwYXNzd29yZD86IHN0cmluZyB8IG51bGwpOiBQcm9taXNlPHsgbWVtb0lkOiBzdHJpbmc7IHNob3J0Q29kZTogc3RyaW5nIH0+IHtcbiAgICBjb25zb2xlLmxvZyhgXHVEODNEXHVEQ0REIENyZWF0aW5nIG1lbW8gd2l0aCBzaG9ydENvZGU6ICR7c2hvcnRDb2RlfWApO1xuICAgIGlmIChwYXNzd29yZCkge1xuICAgICAgY29uc29sZS5sb2coYFx1RDgzRFx1REQxMiBQYXNzd29yZCBwcm90ZWN0aW9uIGVuYWJsZWRgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjcmVhdGVNZW1vRnVuY3Rpb24gPSBodHRwc0NhbGxhYmxlKGZ1bmN0aW9ucywgJ2NyZWF0ZU1lbW8nKTtcblxuICAgIGNvbnN0IHJlcXVlc3Q6IENyZWF0ZU1lbW9SZXF1ZXN0ID0ge1xuICAgICAgc2hvcnRDb2RlLFxuICAgICAgaXNQdWJsaWM6IHRydWUsXG4gICAgICBjb250ZW50VHlwZTogJ21hcmtkb3duJyxcbiAgICB9O1xuXG4gICAgLy8gQWRkIHBhc3N3b3JkIGlmIHByb3ZpZGVkXG4gICAgaWYgKHBhc3N3b3JkKSB7XG4gICAgICByZXF1ZXN0LnBhc3N3b3JkID0gcGFzc3dvcmQ7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY3JlYXRlTWVtb0Z1bmN0aW9uKHJlcXVlc3QpO1xuICAgIGNvbnN0IGRhdGEgPSByZXN1bHQuZGF0YSBhcyBhbnk7XG5cbiAgICBpZiAoIWRhdGEuc3VjY2Vzcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuZXJyb3IgfHwgJ0ZhaWxlZCB0byBjcmVhdGUgbWVtbycpO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGBcdTI3MDUgTWVtbyBjcmVhdGVkOiAke2RhdGEubWVtb0lkfWApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIG1lbW9JZDogZGF0YS5tZW1vSWQsXG4gICAgICBzaG9ydENvZGU6IGRhdGEuc2hvcnRDb2RlLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSBtYXJrZG93biBjb250ZW50IHRvIG1lbW9cbiAgICovXG4gIGFzeW5jIHNhdmVNZW1vKFxuICAgIG1lbW9JZDogc3RyaW5nLFxuICAgIHNob3J0Q29kZTogc3RyaW5nLFxuICAgIGNvbnRlbnQ6IHN0cmluZyxcbiAgICBpbWFnZXM6IEFycmF5PGFueT4sXG4gICAgaW50ZXJuYWxMaW5rczogc3RyaW5nW10sXG4gICAgdmVyc2lvbj86IG51bWJlcixcbiAgICBwYXNzd29yZD86IHN0cmluZyB8IG51bGxcbiAgKTogUHJvbWlzZTxNZW1vVXBsb2FkUmVzdWx0PiB7XG4gICAgY29uc29sZS5sb2coYFx1RDgzRFx1RENCRSBTYXZpbmcgbWVtbzogJHtzaG9ydENvZGV9YCk7XG5cbiAgICBjb25zdCBzYXZlTWVtb0Z1bmN0aW9uID0gaHR0cHNDYWxsYWJsZShmdW5jdGlvbnMsICdzYXZlTWVtbycpO1xuXG4gICAgY29uc3QgcmVxdWVzdDogYW55ID0ge1xuICAgICAgc2hvcnRDb2RlLFxuICAgICAgbWVtb0lkLFxuICAgICAgbWFya2Rvd25EYXRhOiB7XG4gICAgICAgIGNvbnRlbnQsXG4gICAgICAgIGltYWdlczogaW1hZ2VzLm1hcCgoaW1nLCBpbmRleCkgPT4gKHtcbiAgICAgICAgICBpZDogYGltZ18ke2luZGV4fWAsXG4gICAgICAgICAgc3RvcmFnZVBhdGg6IGltZy5zdG9yYWdlUGF0aCxcbiAgICAgICAgICBvcmlnaW5hbE5hbWU6IGltZy5vcmlnaW5hbE5hbWUsXG4gICAgICAgICAgbWltZVR5cGU6IGltZy5taW1lVHlwZSxcbiAgICAgICAgICBzaXplOiBpbWcuc2l6ZSxcbiAgICAgICAgICBhbHRUZXh0OiBpbWcuYWx0VGV4dCxcbiAgICAgICAgfSkpLFxuICAgICAgICBpbnRlcm5hbExpbmtzLFxuICAgICAgfSxcbiAgICAgIHZlcnNpb24sXG4gICAgfTtcblxuICAgIC8vIEFkZCBwYXNzd29yZCBpZiBwcm92aWRlZFxuICAgIGlmIChwYXNzd29yZCkge1xuICAgICAgcmVxdWVzdC5wYXNzd29yZCA9IHBhc3N3b3JkO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNhdmVNZW1vRnVuY3Rpb24ocmVxdWVzdCk7XG4gICAgY29uc3QgZGF0YSA9IHJlc3VsdC5kYXRhIGFzIGFueTtcblxuICAgIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZGF0YS5lcnJvciB8fCAnRmFpbGVkIHRvIHNhdmUgbWVtbycpO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGBcdTI3MDUgTWVtbyBzYXZlZCBzdWNjZXNzZnVsbHkuIFZlcnNpb246ICR7ZGF0YS52ZXJzaW9ufWApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICBtZW1vSWQsXG4gICAgICBzaG9ydENvZGUsXG4gICAgICB1cmw6IGBodHRwczovL3V1dS5nbC9tZC8ke3Nob3J0Q29kZX1gLFxuICAgICAgdmVyc2lvbjogZGF0YS52ZXJzaW9uIHx8IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wbGV0ZSB1cGxvYWQgd29ya2Zsb3c6IGNyZWF0ZSArIHNhdmVcbiAgICovXG4gIGFzeW5jIHVwbG9hZE1hcmtkb3duKFxuICAgIHNob3J0Q29kZTogc3RyaW5nLFxuICAgIGNvbnRlbnQ6IHN0cmluZyxcbiAgICBpbWFnZXM6IEFycmF5PGFueT4sXG4gICAgaW50ZXJuYWxMaW5rczogc3RyaW5nW11cbiAgKTogUHJvbWlzZTxNZW1vVXBsb2FkUmVzdWx0PiB7XG4gICAgLy8gMS4gQ3JlYXRlIG1lbW9cbiAgICBjb25zdCB7IG1lbW9JZCwgc2hvcnRDb2RlOiBmaW5hbFNob3J0Q29kZSB9ID0gYXdhaXQgdGhpcy5jcmVhdGVNZW1vKHNob3J0Q29kZSk7XG5cbiAgICAvLyAyLiBTYXZlIGNvbnRlbnRcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnNhdmVNZW1vKFxuICAgICAgbWVtb0lkLFxuICAgICAgZmluYWxTaG9ydENvZGUsXG4gICAgICBjb250ZW50LFxuICAgICAgaW1hZ2VzLFxuICAgICAgaW50ZXJuYWxMaW5rcyxcbiAgICAgIDAgLy8gSW5pdGlhbCB2ZXJzaW9uXG4gICAgKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiIsICIvKipcbiAqIFBsdWdpbiBTZXR0aW5ncyBVSVxuICovXG5cbmltcG9ydCB7IEFwcCwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZywgTm90aWNlIH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IFV1dWdsUGx1Z2luIGZyb20gJy4vbWFpbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXV1Z2xQbHVnaW5TZXR0aW5ncyB7XG4gIGVtYWlsOiBzdHJpbmc7XG4gIHVpZDogc3RyaW5nO1xuICBmaW5nZXJwcmludDogc3RyaW5nO1xuICBsYXN0U3luY2VkQXQ6IHN0cmluZztcbiAgZGVmYXVsdFNob3J0Q29kZVByZWZpeDogc3RyaW5nO1xuICB1cmxDYWNoZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPjsgLy8gZmlsZSBwYXRoIC0+IHV1dS5nbCBVUkwgbWFwcGluZ1xufVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogVXV1Z2xQbHVnaW5TZXR0aW5ncyA9IHtcbiAgZW1haWw6ICcnLFxuICB1aWQ6ICcnLFxuICBmaW5nZXJwcmludDogJycsXG4gIGxhc3RTeW5jZWRBdDogJycsXG4gIGRlZmF1bHRTaG9ydENvZGVQcmVmaXg6ICdvYnNpZGlhbicsXG4gIHVybENhY2hlOiB7fSwgLy8gUGVyc2lzdGVudCBVUkwgY2FjaGVcbn07XG5cbmV4cG9ydCBjbGFzcyBVdXVnbFNldHRpbmdUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcbiAgcGx1Z2luOiBVdXVnbFBsdWdpbjtcblxuICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBVdXVnbFBsdWdpbikge1xuICAgIHN1cGVyKGFwcCwgcGx1Z2luKTtcbiAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcbiAgfVxuXG4gIGRpc3BsYXkoKTogdm9pZCB7XG4gICAgY29uc3QgeyBjb250YWluZXJFbCB9ID0gdGhpcztcblxuICAgIGNvbnRhaW5lckVsLmVtcHR5KCk7XG5cbiAgICAvLyBIZWFkZXJcbiAgICBjb250YWluZXJFbC5jcmVhdGVFbCgnaDInLCB7IHRleHQ6ICd1dXUuZ2wgTWFya2Rvd24gVXBsb2FkZXIgU2V0dGluZ3MnIH0pO1xuXG4gICAgLy8gRGVzY3JpcHRpb25cbiAgICBjb250YWluZXJFbC5jcmVhdGVFbCgncCcsIHtcbiAgICAgIHRleHQ6ICdVcGxvYWQgeW91ciBPYnNpZGlhbiBub3RlcyB0byB1dXUuZ2wgYXMgYmVhdXRpZnVsbHkgcmVuZGVyZWQgTWFya2Rvd24gZG9jdW1lbnRzLicsXG4gICAgICBjbHM6ICdzZXR0aW5nLWl0ZW0tZGVzY3JpcHRpb24nLFxuICAgIH0pO1xuXG4gICAgLy8gQXV0aGVudGljYXRpb24gU2VjdGlvblxuICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMycsIHsgdGV4dDogJ0F1dGhlbnRpY2F0aW9uJyB9KTtcblxuICAgIC8vIEN1cnJlbnQgdXNlciBzdGF0dXNcbiAgICBjb25zdCBjdXJyZW50VXNlciA9IHRoaXMucGx1Z2luLmF1dGhNYW5hZ2VyLmdldEN1cnJlbnRVc2VyKCk7XG4gICAgaWYgKGN1cnJlbnRVc2VyKSB7XG4gICAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgICAgLnNldE5hbWUoJ0xvZ2dlZCBpbiBhcycpXG4gICAgICAgIC5zZXREZXNjKGN1cnJlbnRVc2VyLmVtYWlsIHx8ICdObyBlbWFpbCcpXG4gICAgICAgIC5hZGRCdXR0b24oKGJ1dHRvbikgPT5cbiAgICAgICAgICBidXR0b25cbiAgICAgICAgICAgIC5zZXRCdXR0b25UZXh0KCdTaWduIE91dCcpXG4gICAgICAgICAgICAub25DbGljayhhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLmF1dGhNYW5hZ2VyLnNpZ25PdXQoKTtcbiAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZW1haWwgPSAnJztcbiAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MudWlkID0gJyc7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICB0aGlzLmRpc3BsYXkoKTsgLy8gUmVmcmVzaCBzZXR0aW5ncyBVSVxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgIC5zZXROYW1lKCdHb29nbGUgU2lnbiBJbicpXG4gICAgICAgIC5zZXREZXNjKCdTaWduIGluIHdpdGggeW91ciBHb29nbGUgYWNjb3VudCB0byB1cGxvYWQgbm90ZXMnKVxuICAgICAgICAuYWRkQnV0dG9uKChidXR0b24pID0+XG4gICAgICAgICAgYnV0dG9uXG4gICAgICAgICAgICAuc2V0QnV0dG9uVGV4dCgnU2lnbiBJbiB3aXRoIEdvb2dsZScpXG4gICAgICAgICAgICAuc2V0Q3RhKClcbiAgICAgICAgICAgIC5vbkNsaWNrKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBidXR0b24uc2V0RGlzYWJsZWQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgYnV0dG9uLnNldEJ1dHRvblRleHQoJ1NpZ25pbmcgaW4uLi4nKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLnBsdWdpbi5hdXRoTWFuYWdlci5zaWduSW5XaXRoR29vZ2xlKCk7XG4gICAgICAgICAgICAgICAgaWYgKHVzZXIuZW1haWwgJiYgdXNlci51aWQpIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmVtYWlsID0gdXNlci5lbWFpbDtcbiAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLnVpZCA9IHVzZXIudWlkO1xuICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheSgpOyAvLyBSZWZyZXNoIHNldHRpbmdzIFVJXG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdTaWduIGluIGZhaWxlZDonLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgbmV3IE5vdGljZShgXHUyNzRDIFNpZ24gaW4gZmFpbGVkOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgICAgICAgYnV0dG9uLnNldERpc2FibGVkKGZhbHNlKTtcbiAgICAgICAgICAgICAgICBidXR0b24uc2V0QnV0dG9uVGV4dCgnU2lnbiBJbiB3aXRoIEdvb2dsZScpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8vIFN0b3JhZ2UgVXNhZ2UgU2VjdGlvblxuICAgIGlmIChjdXJyZW50VXNlcikge1xuICAgICAgY29udGFpbmVyRWwuY3JlYXRlRWwoJ2gzJywgeyB0ZXh0OiAnU3RvcmFnZSBVc2FnZScgfSk7XG5cbiAgICAgIGNvbnN0IHN0b3JhZ2VDb250YWluZXIgPSBjb250YWluZXJFbC5jcmVhdGVEaXYoeyBjbHM6ICdzdG9yYWdlLXVzYWdlLWNvbnRhaW5lcicgfSk7XG4gICAgICBzdG9yYWdlQ29udGFpbmVyLmNyZWF0ZUVsKCdwJywgeyB0ZXh0OiAnTG9hZGluZyBzdG9yYWdlIGluZm9ybWF0aW9uLi4uJyB9KTtcblxuICAgICAgLy8gRmV0Y2ggc3RvcmFnZSBzdGF0c1xuICAgICAgdGhpcy5mZXRjaFN0b3JhZ2VTdGF0cyhzdG9yYWdlQ29udGFpbmVyKTtcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IFNob3J0Q29kZSBQcmVmaXhcbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgIC5zZXROYW1lKCdEZWZhdWx0IFNob3J0Q29kZSBQcmVmaXgnKVxuICAgICAgLnNldERlc2MoJ1ByZWZpeCBmb3IgYXV0by1nZW5lcmF0ZWQgc2hvcnRjb2RlcyAoZS5nLiwgXCJvYnNpZGlhbi9teS1ub3RlXCIpJylcbiAgICAgIC5hZGRUZXh0KCh0ZXh0KSA9PlxuICAgICAgICB0ZXh0XG4gICAgICAgICAgLnNldFBsYWNlaG9sZGVyKCdvYnNpZGlhbicpXG4gICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRTaG9ydENvZGVQcmVmaXgpXG4gICAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdFNob3J0Q29kZVByZWZpeCA9IHZhbHVlO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICAvLyBGaW5nZXJwcmludCAoUmVhZC1vbmx5KVxuICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgLnNldE5hbWUoJ0RldmljZSBGaW5nZXJwcmludCcpXG4gICAgICAuc2V0RGVzYygnVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoaXMgZGV2aWNlIChhdXRvLWdlbmVyYXRlZCknKVxuICAgICAgLmFkZFRleHQoKHRleHQpID0+XG4gICAgICAgIHRleHRcbiAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZmluZ2VycHJpbnQgfHwgJ05vdCBnZW5lcmF0ZWQgeWV0JylcbiAgICAgICAgICAuc2V0RGlzYWJsZWQodHJ1ZSlcbiAgICAgICk7XG5cbiAgICAvLyBMYXN0IFN5bmNlZFxuICAgIGlmICh0aGlzLnBsdWdpbi5zZXR0aW5ncy5sYXN0U3luY2VkQXQpIHtcbiAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAuc2V0TmFtZSgnTGFzdCBVcGxvYWQnKVxuICAgICAgICAuc2V0RGVzYygnV2hlbiB5b3UgbGFzdCB1cGxvYWRlZCBhIG5vdGUnKVxuICAgICAgICAuYWRkVGV4dCgodGV4dCkgPT5cbiAgICAgICAgICB0ZXh0XG4gICAgICAgICAgICAuc2V0VmFsdWUobmV3IERhdGUodGhpcy5wbHVnaW4uc2V0dGluZ3MubGFzdFN5bmNlZEF0KS50b0xvY2FsZVN0cmluZygpKVxuICAgICAgICAgICAgLnNldERpc2FibGVkKHRydWUpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRGl2aWRlclxuICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdocicpO1xuXG4gICAgLy8gSG93IHRvIFVzZVxuICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMycsIHsgdGV4dDogJ0hvdyB0byBVc2UnIH0pO1xuXG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25zTGlzdCA9IGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdvbCcpO1xuICAgIGluc3RydWN0aW9uc0xpc3QuY3JlYXRlRWwoJ2xpJywgeyB0ZXh0OiAnRW50ZXIgeW91ciBlbWFpbCBhZGRyZXNzIGFib3ZlJyB9KTtcbiAgICBpbnN0cnVjdGlvbnNMaXN0LmNyZWF0ZUVsKCdsaScsIHsgdGV4dDogJ09wZW4gYW55IG5vdGUgaW4gT2JzaWRpYW4nIH0pO1xuICAgIGluc3RydWN0aW9uc0xpc3QuY3JlYXRlRWwoJ2xpJywgeyB0ZXh0OiAnQ2xpY2sgdGhlIHVwbG9hZCBpY29uIGluIHRoZSByaWJib24gb3IgdXNlIHRoZSBjb21tYW5kIHBhbGV0dGUnIH0pO1xuICAgIGluc3RydWN0aW9uc0xpc3QuY3JlYXRlRWwoJ2xpJywgeyB0ZXh0OiAnQ2hvb3NlIGEgc2hvcnRjb2RlIChVUkwgcGF0aCkgZm9yIHlvdXIgbm90ZScgfSk7XG4gICAgaW5zdHJ1Y3Rpb25zTGlzdC5jcmVhdGVFbCgnbGknLCB7IHRleHQ6ICdZb3VyIG5vdGUgd2lsbCBiZSB1cGxvYWRlZCB3aXRoIGFsbCBpbWFnZXMgYW5kIGludGVybmFsIGxpbmtzIHByZXNlcnZlZCEnIH0pO1xuXG4gICAgLy8gU3VwcG9ydCBMaW5rXG4gICAgY29udGFpbmVyRWwuY3JlYXRlRWwoJ3AnLCB7XG4gICAgICB0ZXh0OiAnTmVlZCBoZWxwPyBWaXNpdCAnLFxuICAgIH0pLmNyZWF0ZUVsKCdhJywge1xuICAgICAgdGV4dDogJ3V1dS5nbCcsXG4gICAgICBocmVmOiAnaHR0cHM6Ly91dXUuZ2wnLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoIGFuZCBkaXNwbGF5IHN0b3JhZ2Ugc3RhdGlzdGljc1xuICAgKi9cbiAgYXN5bmMgZmV0Y2hTdG9yYWdlU3RhdHMoY29udGFpbmVyOiBIVE1MRWxlbWVudCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB0b2tlbiA9IGF3YWl0IHRoaXMucGx1Z2luLmF1dGhNYW5hZ2VyLmdldElkVG9rZW4oKTtcblxuICAgICAgLy8gQ2FsbCBnZXRVc2VyU3RhdHMgQ2xvdWQgRnVuY3Rpb24gdXNpbmcgRmlyZWJhc2UgRnVuY3Rpb25zIFNES1xuICAgICAgY29uc3QgeyBmdW5jdGlvbnMgfSA9IGF3YWl0IGltcG9ydCgnLi9maXJlYmFzZS1jb25maWcnKTtcbiAgICAgIGNvbnN0IHsgaHR0cHNDYWxsYWJsZSB9ID0gYXdhaXQgaW1wb3J0KCdmaXJlYmFzZS9mdW5jdGlvbnMnKTtcblxuICAgICAgY29uc3QgZ2V0VXNlclN0YXRzID0gaHR0cHNDYWxsYWJsZShmdW5jdGlvbnMsICdnZXRVc2VyU3RhdHMnKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldFVzZXJTdGF0cyh7fSk7XG4gICAgICBjb25zdCBzdGF0cyA9IHJlc3VsdC5kYXRhIGFzIGFueTtcblxuICAgICAgLy8gQ2xlYXIgbG9hZGluZyBtZXNzYWdlXG4gICAgICBjb250YWluZXIuZW1wdHkoKTtcblxuICAgICAgLy8gRm9ybWF0IGJ5dGVzIHRvIGh1bWFuLXJlYWRhYmxlXG4gICAgICBjb25zdCBmb3JtYXRCeXRlcyA9IChieXRlczogbnVtYmVyKSA9PiB7XG4gICAgICAgIGlmIChieXRlcyA9PT0gMCkgcmV0dXJuICcwIEInO1xuICAgICAgICBjb25zdCBrID0gMTAyNDtcbiAgICAgICAgY29uc3Qgc2l6ZXMgPSBbJ0InLCAnS0InLCAnTUInLCAnR0InXTtcbiAgICAgICAgY29uc3QgaSA9IE1hdGguZmxvb3IoTWF0aC5sb2coYnl0ZXMpIC8gTWF0aC5sb2coaykpO1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChieXRlcyAvIE1hdGgucG93KGssIGkpICogMTAwKSAvIDEwMCArICcgJyArIHNpemVzW2ldO1xuICAgICAgfTtcblxuICAgICAgLy8gU3RvcmFnZSB1c2FnZSBiYXJcbiAgICAgIGNvbnN0IHVzZWRCeXRlcyA9IHN0YXRzLnN0b3JhZ2VVc2VkIHx8IDA7XG4gICAgICBjb25zdCBsaW1pdEJ5dGVzID0gc3RhdHMuc3RvcmFnZUxpbWl0IHx8IDA7XG4gICAgICBjb25zdCB1c2VkRm9ybWF0dGVkID0gZm9ybWF0Qnl0ZXModXNlZEJ5dGVzKTtcbiAgICAgIGNvbnN0IGxpbWl0Rm9ybWF0dGVkID0gbGltaXRCeXRlcyA9PT0gLTEgPyAnVW5saW1pdGVkJyA6IGZvcm1hdEJ5dGVzKGxpbWl0Qnl0ZXMpO1xuICAgICAgY29uc3QgcGVyY2VudGFnZSA9IGxpbWl0Qnl0ZXMgPT09IC0xID8gMCA6IE1hdGgubWluKDEwMCwgKHVzZWRCeXRlcyAvIGxpbWl0Qnl0ZXMpICogMTAwKTtcblxuICAgICAgLy8gQ3JlYXRlIHN0b3JhZ2UgZGlzcGxheVxuICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyKVxuICAgICAgICAuc2V0TmFtZSgnU3RvcmFnZSBVc2VkJylcbiAgICAgICAgLnNldERlc2MoYCR7dXNlZEZvcm1hdHRlZH0gLyAke2xpbWl0Rm9ybWF0dGVkfWApXG4gICAgICAgIC5zZXRDbGFzcygnc3RvcmFnZS1zdGF0Jyk7XG5cbiAgICAgIC8vIFByb2dyZXNzIGJhclxuICAgICAgY29uc3QgcHJvZ3Jlc3NDb250YWluZXIgPSBjb250YWluZXIuY3JlYXRlRGl2KHsgY2xzOiAnc3RvcmFnZS1wcm9ncmVzcycgfSk7XG4gICAgICBwcm9ncmVzc0NvbnRhaW5lci5jcmVhdGVFbCgnZGl2Jywge1xuICAgICAgICBjbHM6ICdzdG9yYWdlLXByb2dyZXNzLWJhcicsXG4gICAgICAgIGF0dHI6IHtcbiAgICAgICAgICBzdHlsZTogYHdpZHRoOiAke3BlcmNlbnRhZ2V9JTsgYmFja2dyb3VuZC1jb2xvcjogJHtcbiAgICAgICAgICAgIHBlcmNlbnRhZ2UgPiA5MCA/ICcjZWY0NDQ0JyA6IHBlcmNlbnRhZ2UgPiA3MCA/ICcjZjU5ZTBiJyA6ICcjMjJjNTVlJ1xuICAgICAgICAgIH1gLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIEFkZGl0aW9uYWwgc3RhdHNcbiAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lcilcbiAgICAgICAgLnNldE5hbWUoJ1RvdGFsIFVSTHMnKVxuICAgICAgICAuc2V0RGVzYyhgJHtzdGF0cy51cmxDb3VudCB8fCAwfSBVUkxzIGNyZWF0ZWRgKTtcblxuICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyKVxuICAgICAgICAuc2V0TmFtZSgnVG90YWwgRmlsZXMnKVxuICAgICAgICAuc2V0RGVzYyhgJHtzdGF0cy5maWxlQ291bnQgfHwgMH0gZmlsZXMgdXBsb2FkZWRgKTtcblxuICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyKVxuICAgICAgICAuc2V0TmFtZSgnVG90YWwgQ2xpY2tzJylcbiAgICAgICAgLnNldERlc2MoYCR7c3RhdHMudG90YWxDbGlja3MgfHwgMH0gY2xpY2tzIG9uIHlvdXIgVVJMc2ApO1xuXG4gICAgICAvLyBBZGQgQ1NTIGZvciBwcm9ncmVzcyBiYXJcbiAgICAgIGlmICghZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3V1dWdsLXN0b3JhZ2Utc3R5bGVzJykpIHtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuICAgICAgICBzdHlsZS5pZCA9ICd1dXVnbC1zdG9yYWdlLXN0eWxlcyc7XG4gICAgICAgIHN0eWxlLnRleHRDb250ZW50ID0gYFxuICAgICAgICAgIC5zdG9yYWdlLXByb2dyZXNzIHtcbiAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICAgICAgaGVpZ2h0OiA4cHg7XG4gICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1iYWNrZ3JvdW5kLW1vZGlmaWVyLWJvcmRlcik7XG4gICAgICAgICAgICBib3JkZXItcmFkaXVzOiA0cHg7XG4gICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICAgICAgbWFyZ2luOiAxMHB4IDA7XG4gICAgICAgICAgfVxuICAgICAgICAgIC5zdG9yYWdlLXByb2dyZXNzLWJhciB7XG4gICAgICAgICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjNzIGVhc2U7XG4gICAgICAgICAgICBib3JkZXItcmFkaXVzOiA0cHg7XG4gICAgICAgICAgfVxuICAgICAgICAgIC5zdG9yYWdlLXVzYWdlLWNvbnRhaW5lciB7XG4gICAgICAgICAgICBwYWRkaW5nOiAxMHB4IDA7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gZmV0Y2ggc3RvcmFnZSBzdGF0czonLCBlcnJvcik7XG4gICAgICBjb250YWluZXIuZW1wdHkoKTtcbiAgICAgIGNvbnRhaW5lci5jcmVhdGVFbCgncCcsIHtcbiAgICAgICAgdGV4dDogJ0ZhaWxlZCB0byBsb2FkIHN0b3JhZ2UgaW5mb3JtYXRpb24nLFxuICAgICAgICBjbHM6ICdtb2Qtd2FybmluZycsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLElBQU07QUFBTjtBQUFBO0FBQUEsSUFBTSw2QkFBNkIsTUFBTztBQUFBO0FBQUE7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SUFBQSxHQUNFO0lBRUY7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBR0Y7TUFBQTs7SUFBQSxHQUFvQztJQUNwQztNQUFBOztJQUFBLEdBQ0U7SUFHRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFJRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQStCO0lBQy9CO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUlGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FBc0M7SUFDdEM7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBR0Y7TUFBQTs7SUFBQSxHQUFrQztJQUNsQztNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFHRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQStCO0lBQy9CO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUVGO01BQUE7O0lBQUEsR0FDRTtJQUdGO01BQUE7O0lBQUEsR0FDRTtJQUdGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FDRTtJQUNGO01BQUE7O0lBQUEsR0FBeUI7SUFDekI7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBRUY7TUFBQTs7SUFBQSxHQUNFO0lBRUY7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBRUY7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUNFO0lBQ0Y7TUFBQTs7SUFBQSxHQUFpQztJQUNqQztNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFJRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQ0U7SUFDRjtNQUFBOztJQUFBLEdBQWtDO0lBQ2xDO01BQUE7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QUFJLElBQUk7QUFBQSxNQUNuQztBQUFBLE1BQU87QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQzdHO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUNoSDtBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTTtBQUFBLE1BQU87QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBLE1BQU07QUFBQSxNQUFNO0FBQUEsTUFDOUc7QUFBQSxNQUFNO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFDL0c7QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFPO0FBQUEsTUFBTztBQUFBLE1BQU87QUFBQSxNQUFNO0FBQUEsTUFBTTtBQUFBO0FBQUE7QUFBQSxJQUcxRCxDQUFDO0FBQ0QsUUFBTSx1QkFBdUIsb0JBQUksSUFBSTtBQUFBLE1BQ2pDO0FBQUEsTUFDQTtB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VUFBQTs7UUFBQSxHQUFnQztRQUNoQztVQUFBOztRQUFBLEdBQ0U7UUFFRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFHRjtVQUFBOztRQUFBLEdBQW9DO1FBQ3BDO1VBQUE7O1FBQUEsR0FDRTtRQUdGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUlGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FBK0I7UUFDL0I7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBSUY7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUFzQztRQUN0QztVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFHRjtVQUFBOztRQUFBLEdBQWtDO1FBQ2xDO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUdGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FBK0I7UUFDL0I7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBRUY7VUFBQTs7UUFBQSxHQUNFO1FBR0Y7VUFBQTs7UUFBQSxHQUNFO1FBR0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUNFO1FBQ0Y7VUFBQTs7UUFBQSxHQUF5QjtRQUN6QjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFFRjtVQUFBOztRQUFBLEdBQ0U7UUFFRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFFRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQ0U7UUFDRjtVQUFBOztRQUFBLEdBQWlDO1FBQ2pDO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUlGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNGO1VBQUE7O1FBQUEsR0FDRTtRQUNG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R0FBRztBQUM3QixnQkFBTSxNQUFNLEtBQUssUUFBUSxVQUFVLEVBQUUsRUFBRSxLQUFLO0FBQzVDLGNBQUksS0FBSztBQUVQLGlCQUFLLFNBQVMsSUFBSSxLQUFLLE1BQU0sR0FBRztBQUNoQyxtQkFBTztBQUFBLFVBQ1Q7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUVBLGFBQU87QUFBQSxJQUNULFNBQVMsT0FBTztBQUNkLGNBQVEsTUFBTSwrQkFBK0IsS0FBSztBQUNsRCxhQUFPO0FBQUEsSUFDVDtBQUFBLEVBQ0Y7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtPLFlBQVksTUFBYSxLQUFhO0FBQzNDLFNBQUssU0FBUyxJQUFJLEtBQUssTUFBTSxHQUFHO0FBQUEsRUFDbEM7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtPLGVBQWUsTUFBYTtBQUNqQyxTQUFLLFNBQVMsT0FBTyxLQUFLLElBQUk7QUFBQSxFQUNoQztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsTUFBYSxlQUFlO0FBRTFCLFVBQU0sY0FBc0MsQ0FBQztBQUM3QyxlQUFXLENBQUMsVUFBVSxHQUFHLEtBQUssS0FBSyxTQUFTLFFBQVEsR0FBRztBQUNyRCxrQkFBWSxRQUFRLElBQUk7QUFBQSxJQUMxQjtBQUdBLFNBQUssU0FBUyxXQUFXO0FBQ3pCLFVBQU0sS0FBSyxhQUFhO0FBRXhCLFlBQVEsSUFBSSxtQkFBWSxLQUFLLFNBQVMsSUFBSSw2QkFBNkI7QUFBQSxFQUN6RTtBQUNGOyIsCiAgIm5hbWVzIjogWyJuYW1lIiwgInF1ZXJ5c3RyaW5nIiwgInN0cmluZ1RvQnl0ZUFycmF5IiwgIm5hbWUiLCAiaW5pdF9pbmRleF9lc20iLCAiTG9nTGV2ZWwiLCAibmFtZSIsICJuYW1lIiwgInZlcnNpb24iLCAidGFyZ2V0IiwgImFwcCIsICJuYW1lIiwgIkRFRkFVTFRfRU5UUllfTkFNRSIsICJ2ZXJzaW9uIiwgImFwcE5hbWUiLCAiYXBwQ29tcGF0TmFtZSIsICJhbmFseXRpY3NOYW1lIiwgImFuYWx5dGljc0NvbXBhdE5hbWUiLCAiYXBwQ2hlY2tOYW1lIiwgImFwcENoZWNrQ29tcGF0TmFtZSIsICJhdXRoTmFtZSIsICJhdXRoQ29tcGF0TmFtZSIsICJkYXRhYmFzZU5hbWUiLCAiZGF0YWNvbm5lY3ROYW1lIiwgImRhdGFiYXNlQ29tcGF0TmFtZSIsICJmdW5jdGlvbnNOYW1lIiwgImZ1bmN0aW9uc0NvbXBhdE5hbWUiLCAiaW5zdGFsbGF0aW9uc05hbWUiLCAiaW5zdGFsbGF0aW9uc0NvbXBhdE5hbWUiLCAibWVzc2FnaW5nTmFtZSIsICJtZXNzYWdpbmdDb21wYXROYW1lIiwgInBlcmZvcm1hbmNlTmFtZSIsICJwZXJmb3JtYW5jZUNvbXBhdE5hbWUiLCAicmVtb3RlQ29uZmlnTmFtZSIsICJyZW1vdGVDb25maWdDb21wYXROYW1lIiwgInN0b3JhZ2VOYW1lIiwgInN0b3JhZ2VDb21wYXROYW1lIiwgImZpcmVzdG9yZU5hbWUiLCAiZmlyZXN0b3JlQ29tcGF0TmFtZSIsICJhaU5hbWUiLCAicGFja2FnZU5hbWUiLCAibmFtZSIsICJ2ZXJzaW9uIiwgImF1dGgiLCAiZmFjdG9yeSIsICJhcHAiLCAiYXBwbHlBY3Rpb25Db2RlIiwgInNlbmRFbWFpbFZlcmlmaWNhdGlvbiIsICJzZW5kUGFzc3dvcmRSZXNldEVtYWlsIiwgInNlbmRTaWduSW5MaW5rVG9FbWFpbCIsICJzaWduSW5XaXRoRW1haWxMaW5rIiwgInNpZ25JbldpdGhQaG9uZU51bWJlciIsICJsaW5rV2l0aFBob25lTnVtYmVyIiwgInNpZ25JbldpdGhDdXN0b21Ub2tlbiIsICJnZXRJZFRva2VuUmVzcG9uc2UiLCAiYXV0aGVudGljYXRpb24uc2VuZFBhc3N3b3JkUmVzZXRFbWFpbCIsICJhY2NvdW50XG4gICAgICAgIC5yZXNldFBhc3N3b3JkIiwgImFjY291bnQuYXBwbHlBY3Rpb25Db2RlIiwgImFjY291bnQucmVzZXRQYXNzd29yZCIsICJyZXF1ZXN0IiwgImFjdGlvbkNvZGVTZXR0aW5ncyIsICJhcGkuc2VuZFNpZ25JbkxpbmtUb0VtYWlsIiwgImFwaS5zZW5kRW1haWxWZXJpZmljYXRpb24iLCAiYXBpLnZlcmlmeUFuZENoYW5nZUVtYWlsIiwgInVwZGF0ZVByb2ZpbGUiLCAiYXBpVXBkYXRlUHJvZmlsZSIsICJhcGlVcGRhdGVFbWFpbFBhc3N3b3JkIiwgIm5hbWUiLCAidmVyc2lvbiIsICJJRFBfUkVRVUVTVF9VUkkiLCAicmVsb2FkIiwgImpzSGVscGVycy5fcmVjYXB0Y2hhRW50ZXJwcmlzZVNjcmlwdFVybCIsICJqc0hlbHBlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgIC5fbG9hZEpTIiwgImluaXRfaW5kZXhfZXNtIiwgImluaXRfZGlzdCIsICJzdGF0dXMiLCAiY29ubmVjdEZ1bmN0aW9uc0VtdWxhdG9yIiwgImh0dHBzQ2FsbGFibGUiLCAibmFtZSIsICJvcHRpb25zIiwgImh0dHBzQ2FsbGFibGVGcm9tVVJMIiwgImVycm9yIiwgImZhY3RvcnkiLCAiYXBwIiwgInZlcnNpb24iLCAiX2Nvbm5lY3RGdW5jdGlvbnNFbXVsYXRvciIsICJfaHR0cHNDYWxsYWJsZSIsICJfaHR0cHNDYWxsYWJsZUZyb21VUkwiLCAiYXV0aCIsICJkaXN0X2V4cG9ydHMiLCAiaW5pdF9kaXN0IiwgImluaXRfaW5kZXhfZXNtIiwgIm5hbWUiLCAiY2FuY2VsZWQiLCAic3RvcCIsICJlbmNvZGUiLCAiZ2V0QmxvYiIsICJCbG9iQnVpbGRlciIsICJzdGFydCIsICJ1cGxvYWRCeXRlcyIsICJyZWYiLCAiZ2V0RG93bmxvYWRVUkwiLCAicmVxdWVzdHNHZXREb3dubG9hZFVybCIsICJfZ2V0Q2hpbGQiLCAiY29ubmVjdFN0b3JhZ2VFbXVsYXRvciIsICJzdG9yYWdlIiwgInVwbG9hZEJ5dGVzSW50ZXJuYWwiLCAiZ2V0RG93bmxvYWRVUkxJbnRlcm5hbCIsICJyZWZJbnRlcm5hbCIsICJhcHAiLCAiY29ubmVjdEVtdWxhdG9ySW50ZXJuYWwiLCAidmVyc2lvbiIsICJTdG9yYWdlRXJyb3JDb2RlIiwgIkVycm9yQ29kZSIsICJhdXRoIiwgImluaXRfZGlzdCIsICJpbml0X2luZGV4X25vZGVfZXNtIiwgImluaXRfZGlzdCIsICJleHBvcnRzIiwgInZlcnNpb24iLCAibmFtZSIsICJzb3VyY2VzIiwgImluZGV4IiwgIkF1ZGlvQ29udGV4dCIsICJfYSIsICJfYiIsICJkb2N1bWVudCIsICJleHBvcnRzIiwgIkNPTlNUQU5UUyIsICJzdHJpbmdUb0J5dGVBcnJheSIsICJieXRlQXJyYXlUb1N0cmluZyIsICJiYXNlNjQiLCAiRGVjb2RlQmFzZTY0U3RyaW5nRXJyb3IiLCAiYmFzZTY0RW5jb2RlIiwgImJhc2U2NHVybEVuY29kZVdpdGhvdXRQYWRkaW5nIiwgImJhc2U2NERlY29kZSIsICJnZXRHbG9iYWwiLCAiZ2V0RGVmYXVsdHNGcm9tR2xvYmFsIiwgImdldERlZmF1bHRzRnJvbUVudlZhcmlhYmxlIiwgImdldERlZmF1bHRzRnJvbUNvb2tpZSIsICJnZXREZWZhdWx0cyIsICJnZXREZWZhdWx0c0Zyb21Qb3N0aW5zdGFsbCIsICJnZXREZWZhdWx0RW11bGF0b3JIb3N0IiwgImdldERlZmF1bHRFbXVsYXRvckhvc3RuYW1lQW5kUG9ydCIsICJnZXREZWZhdWx0QXBwQ29uZmlnIiwgIm5hbWUiLCAiRGVmZXJyZWQiLCAiaXNDbG91ZFdvcmtzdGF0aW9uIiwgInBpbmdTZXJ2ZXIiLCAiY3JlYXRlTW9ja1VzZXJUb2tlbiIsICJlbXVsYXRvclN0YXR1cyIsICJnZXRFbXVsYXRvclN1bW1hcnkiLCAiZ2V0T3JDcmVhdGVFbCIsICJwcmV2aW91c2x5RGlzbWlzc2VkIiwgInVwZGF0ZUVtdWxhdG9yQmFubmVyIiwgImdldFVBIiwgImlzTW9iaWxlQ29yZG92YSIsICJpc0Jyb3dzZXIiLCAiaXNXZWJXb3JrZXIiLCAiaXNDbG91ZGZsYXJlV29ya2VyIiwgImlzQnJvd3NlckV4dGVuc2lvbiIsICJpc1JlYWN0TmF0aXZlIiwgImlzSUUiLCAiaXNJbmRleGVkREJBdmFpbGFibGUiLCAidmFsaWRhdGVJbmRleGVkREJPcGVuYWJsZSIsICJFUlJPUl9OQU1FIiwgIkZpcmViYXNlRXJyb3IiLCAiRXJyb3JGYWN0b3J5IiwgInJlcGxhY2VUZW1wbGF0ZSIsICJQQVRURVJOIiwgImRlY29kZSIsICJkZWVwRXF1YWwiLCAiaXNPYmplY3QiLCAicXVlcnlzdHJpbmciLCAicXVlcnlzdHJpbmdEZWNvZGUiLCAiZXh0cmFjdFF1ZXJ5c3RyaW5nIiwgImNyZWF0ZVN1YnNjcmliZSIsICJPYnNlcnZlclByb3h5IiwgImltcGxlbWVudHNBbnlNZXRob2RzIiwgIm5vb3AiLCAiTUFYX1ZBTFVFX01JTExJUyIsICJnZXRNb2R1bGFySW5zdGFuY2UiLCAiQ29tcG9uZW50IiwgIm5hbWUiLCAiREVGQVVMVF9FTlRSWV9OQU1FIiwgIlByb3ZpZGVyIiwgIkRlZmVycmVkIiwgImlzQ29tcG9uZW50RWFnZXIiLCAibm9ybWFsaXplSWRlbnRpZmllckZvckZhY3RvcnkiLCAiQ29tcG9uZW50Q29udGFpbmVyIiwgImluc3RhbmNlcyIsICJMb2dMZXZlbCIsICJsZXZlbFN0cmluZ1RvRW51bSIsICJkZWZhdWx0TG9nTGV2ZWwiLCAiQ29uc29sZU1ldGhvZCIsICJkZWZhdWx0TG9nSGFuZGxlciIsICJMb2dnZXIiLCAibmFtZSIsICJzZXRMb2dMZXZlbCIsICJzZXRVc2VyTG9nSGFuZGxlciIsICJpbnN0YW5jZSIsICJQbGF0Zm9ybUxvZ2dlclNlcnZpY2VJbXBsIiwgImlzVmVyc2lvblNlcnZpY2VQcm92aWRlciIsICJjb21wb25lbnQiLCAibG9nZ2VyIiwgIkxvZ2dlciIsICJERUZBVUxUX0VOVFJZX05BTUUiLCAiUExBVEZPUk1fTE9HX1NUUklORyIsICJhcHBOYW1lIiwgImFwcENvbXBhdE5hbWUiLCAiYW5hbHl0aWNzTmFtZSIsICJhbmFseXRpY3NDb21wYXROYW1lIiwgImFwcENoZWNrTmFtZSIsICJhcHBDaGVja0NvbXBhdE5hbWUiLCAiYXV0aE5hbWUiLCAiYXV0aENvbXBhdE5hbWUiLCAiZGF0YWJhc2VOYW1lIiwgImRhdGFjb25uZWN0TmFtZSIsICJkYXRhYmFzZUNvbXBhdE5hbWUiLCAiZnVuY3Rpb25zTmFtZSIsICJmdW5jdGlvbnNDb21wYXROYW1lIiwgImluc3RhbGxhdGlvbnNOYW1lIiwgImluc3RhbGxhdGlvbnNDb21wYXROYW1lIiwgIm1lc3NhZ2luZ05hbWUiLCAibWVzc2FnaW5nQ29tcGF0TmFtZSIsICJwZXJmb3JtYW5jZU5hbWUiLCAicGVyZm9ybWFuY2VDb21wYXROYW1lIiwgInJlbW90ZUNvbmZpZ05hbWUiLCAicmVtb3RlQ29uZmlnQ29tcGF0TmFtZSIsICJzdG9yYWdlTmFtZSIsICJzdG9yYWdlQ29tcGF0TmFtZSIsICJmaXJlc3RvcmVOYW1lIiwgImZpcmVzdG9yZUNvbXBhdE5hbWUiLCAiYWlOYW1lIiwgInBhY2thZ2VOYW1lIiwgIl9hcHBzIiwgIl9zZXJ2ZXJBcHBzIiwgIl9jb21wb25lbnRzIiwgIl9hZGRDb21wb25lbnQiLCAiYXBwIiwgIl9yZWdpc3RlckNvbXBvbmVudCIsICJfZ2V0UHJvdmlkZXIiLCAibmFtZSIsICJfaXNGaXJlYmFzZVNlcnZlckFwcCIsICJFUlJPUlMiLCAiRVJST1JfRkFDVE9SWSIsICJFcnJvckZhY3RvcnkiLCAiRmlyZWJhc2VBcHBJbXBsIiwgIkNvbXBvbmVudCIsICJiYXNlNjREZWNvZGUiLCAicmVnaXN0ZXJWZXJzaW9uIiwgInZlcnNpb24iLCAiU0RLX1ZFUlNJT04iLCAiaW5pdGlhbGl6ZUFwcCIsICJnZXREZWZhdWx0QXBwQ29uZmlnIiwgImRlZXBFcXVhbCIsICJDb21wb25lbnRDb250YWluZXIiLCAiaXNCcm93c2VyIiwgImlzV2ViV29ya2VyIiwgImdldEFwcCIsICJzZXRVc2VyTG9nSGFuZGxlciIsICJzZXRMb2dMZXZlbCIsICJzZXRMb2dMZXZlbEltcGwiLCAiREJfTkFNRSIsICJEQl9WRVJTSU9OIiwgIlNUT1JFX05BTUUiLCAiZGJQcm9taXNlIiwgImdldERiUHJvbWlzZSIsICJvcGVuREIiLCAicmVhZEhlYXJ0YmVhdHNGcm9tSW5kZXhlZERCIiwgImNvbXB1dGVLZXkiLCAiRmlyZWJhc2VFcnJvciIsICJ3cml0ZUhlYXJ0YmVhdHNUb0luZGV4ZWREQiIsICJNQVhfSEVBREVSX0JZVEVTIiwgIk1BWF9OVU1fU1RPUkVEX0hFQVJUQkVBVFMiLCAiSGVhcnRiZWF0U2VydmljZUltcGwiLCAiSGVhcnRiZWF0U3RvcmFnZUltcGwiLCAiZ2V0VVRDRGF0ZVN0cmluZyIsICJnZXRFYXJsaWVzdEhlYXJ0YmVhdElkeCIsICJleHRyYWN0SGVhcnRiZWF0c0ZvckhlYWRlciIsICJiYXNlNjR1cmxFbmNvZGVXaXRob3V0UGFkZGluZyIsICJjb3VudEJ5dGVzIiwgImlzSW5kZXhlZERCQXZhaWxhYmxlIiwgInZhbGlkYXRlSW5kZXhlZERCT3BlbmFibGUiLCAicmVnaXN0ZXJDb3JlQ29tcG9uZW50cyIsICJGYWN0b3JJZCIsICJQcm92aWRlcklkIiwgIlNpZ25Jbk1ldGhvZCIsICJPcGVyYXRpb25UeXBlIiwgIkFjdGlvbkNvZGVPcGVyYXRpb24iLCAiX2RlYnVnRXJyb3JNYXAiLCAiX3Byb2RFcnJvck1hcCIsICJkZWJ1Z0Vycm9yTWFwIiwgInByb2RFcnJvck1hcCIsICJfREVGQVVMVF9BVVRIX0VSUk9SX0ZBQ1RPUlkiLCAiRXJyb3JGYWN0b3J5IiwgIkFVVEhfRVJST1JfQ09ERVNfTUFQX0RPX05PVF9VU0VfSU5URVJOQUxMWSIsICJsb2dDbGllbnQiLCAiTG9nZ2VyIiwgIl9sb2dXYXJuIiwgIkxvZ0xldmVsIiwgIlNES19WRVJTSU9OIiwgIl9sb2dFcnJvciIsICJfZmFpbCIsICJjcmVhdGVFcnJvckludGVybmFsIiwgIl9jcmVhdGVFcnJvciIsICJfZXJyb3JXaXRoQ3VzdG9tTWVzc2FnZSIsICJhdXRoIiwgImZhY3RvcnkiLCAiX3NlcnZlckFwcEN1cnJlbnRVc2VyT3BlcmF0aW9uTm90U3VwcG9ydGVkRXJyb3IiLCAiX2Fzc2VydCIsICJkZWJ1Z0ZhaWwiLCAiZGVidWdBc3NlcnQiLCAiX2dldEN1cnJlbnRVcmwiLCAiX2lzSHR0cE9ySHR0cHMiLCAiX2dldEN1cnJlbnRTY2hlbWUiLCAiX2lzT25saW5lIiwgImlzQnJvd3NlckV4dGVuc2lvbiIsICJfZ2V0VXNlckxhbmd1YWdlIiwgIkRlbGF5IiwgImlzTW9iaWxlQ29yZG92YSIsICJpc1JlYWN0TmF0aXZlIiwgIl9lbXVsYXRvclVybCIsICJGZXRjaFByb3ZpZGVyIiwgIlNFUlZFUl9FUlJPUl9NQVAiLCAiQ29va2llQXV0aFByb3hpZWRFbmRwb2ludHMiLCAiREVGQVVMVF9BUElfVElNRU9VVF9NUyIsICJfYWRkVGlkSWZOZWNlc3NhcnkiLCAiX3BlcmZvcm1BcGlSZXF1ZXN0IiwgIl9wZXJmb3JtRmV0Y2hXaXRoRXJyb3JIYW5kbGluZyIsICJxdWVyeXN0cmluZyIsICJpc0Nsb3VkZmxhcmVXb3JrZXIiLCAiaXNDbG91ZFdvcmtzdGF0aW9uIiwgIl9nZXRGaW5hbFRhcmdldCIsICJOZXR3b3JrVGltZW91dCIsICJfbWFrZVRhZ2dlZEVycm9yIiwgIkZpcmViYXNlRXJyb3IiLCAiX3BlcmZvcm1TaWduSW5SZXF1ZXN0IiwgIl9wYXJzZUVuZm9yY2VtZW50U3RhdGUiLCAiaXNFbnRlcnByaXNlIiwgIlJlY2FwdGNoYUNvbmZpZyIsICJnZXRSZWNhcHRjaGFDb25maWciLCAiZGVsZXRlQWNjb3VudCIsICJkZWxldGVMaW5rZWRBY2NvdW50cyIsICJnZXRBY2NvdW50SW5mbyIsICJ1dGNUaW1lc3RhbXBUb0RhdGVTdHJpbmciLCAiZ2V0SWRUb2tlbiIsICJnZXRNb2R1bGFySW5zdGFuY2UiLCAiZ2V0SWRUb2tlblJlc3VsdCIsICJfcGFyc2VUb2tlbiIsICJzZWNvbmRzU3RyaW5nVG9NaWxsaXNlY29uZHMiLCAiYmFzZTY0RGVjb2RlIiwgIl90b2tlbkV4cGlyZXNJbiIsICJfbG9nb3V0SWZJbnZhbGlkYXRlZCIsICJpc1VzZXJJbnZhbGlkYXRlZCIsICJQcm9hY3RpdmVSZWZyZXNoIiwgIlVzZXJNZXRhZGF0YSIsICJfcmVsb2FkV2l0aG91dFNhdmluZyIsICJleHRyYWN0UHJvdmlkZXJEYXRhIiwgIm1lcmdlUHJvdmlkZXJEYXRhIiwgInJlbG9hZCIsICJyZXF1ZXN0U3RzVG9rZW4iLCAicmV2b2tlVG9rZW4iLCAiU3RzVG9rZW5NYW5hZ2VyIiwgImFzc2VydFN0cmluZ09yVW5kZWZpbmVkIiwgIlVzZXJJbXBsIiwgIl9pc0ZpcmViYXNlU2VydmVyQXBwIiwgImluc3RhbmNlQ2FjaGUiLCAiX2dldEluc3RhbmNlIiwgIkluTWVtb3J5UGVyc2lzdGVuY2UiLCAiaW5NZW1vcnlQZXJzaXN0ZW5jZSIsICJfcGVyc2lzdGVuY2VLZXlOYW1lIiwgIlBlcnNpc3RlbmNlVXNlck1hbmFnZXIiLCAibmFtZSIsICJfZ2V0QnJvd3Nlck5hbWUiLCAiX2lzSUVNb2JpbGUiLCAiX2lzRmlyZWZveCIsICJfaXNCbGFja0JlcnJ5IiwgIl9pc1dlYk9TIiwgIl9pc1NhZmFyaSIsICJfaXNDaHJvbWVJT1MiLCAiX2lzQW5kcm9pZCIsICJnZXRVQSIsICJpc0lFIiwgIl9nZXRDbGllbnRWZXJzaW9uIiwgIkF1dGhNaWRkbGV3YXJlUXVldWUiLCAiX2dldFBhc3N3b3JkUG9saWN5IiwgIk1JTklNVU1fTUlOX1BBU1NXT1JEX0xFTkdUSCIsICJQYXNzd29yZFBvbGljeUltcGwiLCAiQXV0aEltcGwiLCAiYXBwIiwgIlN1YnNjcmlwdGlvbiIsICJfY2FzdEF1dGgiLCAiY3JlYXRlU3Vic2NyaWJlIiwgImV4dGVybmFsSlNQcm92aWRlciIsICJfbG9hZEpTIiwgIl9yZWNhcHRjaGFFbnRlcnByaXNlU2NyaXB0VXJsIiwgIk1vY2tHcmVDQVBUQ0hBVG9wTGV2ZWwiLCAiTW9ja0dyZUNBUFRDSEEiLCAiUkVDQVBUQ0hBX0VOVEVSUFJJU0VfVkVSSUZJRVJfVFlQRSIsICJGQUtFX1RPS0VOIiwgIlJlY2FwdGNoYUVudGVycHJpc2VWZXJpZmllciIsICJqc0hlbHBlcnMuX3JlY2FwdGNoYUVudGVycHJpc2VTY3JpcHRVcmwiLCAianNIZWxwZXJzXG4gICAgICAgICAgICAgICAgICAgICAgICAuX2xvYWRKUyIsICJpbmplY3RSZWNhcHRjaGFGaWVsZHMiLCAiaGFuZGxlUmVjYXB0Y2hhRmxvdyIsICJfaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZyIsICJpbml0aWFsaXplQXV0aCIsICJfZ2V0UHJvdmlkZXIiLCAiZGVlcEVxdWFsIiwgIl9pbml0aWFsaXplQXV0aEluc3RhbmNlIiwgImNvbm5lY3RBdXRoRW11bGF0b3IiLCAiZXh0cmFjdFByb3RvY29sIiwgImV4dHJhY3RIb3N0QW5kUG9ydCIsICJwaW5nU2VydmVyIiwgInVwZGF0ZUVtdWxhdG9yQmFubmVyIiwgImVtaXRFbXVsYXRvcldhcm5pbmciLCAicGFyc2VQb3J0IiwgIkF1dGhDcmVkZW50aWFsIiwgInJlc2V0UGFzc3dvcmQiLCAidXBkYXRlRW1haWxQYXNzd29yZCIsICJsaW5rRW1haWxQYXNzd29yZCIsICJhcHBseUFjdGlvbkNvZGUiLCAic2lnbkluV2l0aFBhc3N3b3JkIiwgInNlbmRPb2JDb2RlIiwgInNlbmRFbWFpbFZlcmlmaWNhdGlvbiIsICJzZW5kUGFzc3dvcmRSZXNldEVtYWlsIiwgInNlbmRTaWduSW5MaW5rVG9FbWFpbCIsICJ2ZXJpZnlBbmRDaGFuZ2VFbWFpbCIsICJzaWduSW5XaXRoRW1haWxMaW5rIiwgInNpZ25JbldpdGhFbWFpbExpbmtGb3JMaW5raW5nIiwgIkVtYWlsQXV0aENyZWRlbnRpYWwiLCAic2lnbkluV2l0aElkcCIsICJJRFBfUkVRVUVTVF9VUkkiLCAiT0F1dGhDcmVkZW50aWFsIiwgInNpZ25JbldpdGhQaG9uZU51bWJlciIsICJsaW5rV2l0aFBob25lTnVtYmVyIiwgIlZFUklGWV9QSE9ORV9OVU1CRVJfRk9SX0VYSVNUSU5HX0VSUk9SX01BUF8iLCAidmVyaWZ5UGhvbmVOdW1iZXJGb3JFeGlzdGluZyIsICJQaG9uZUF1dGhDcmVkZW50aWFsIiwgInBhcnNlTW9kZSIsICJwYXJzZURlZXBMaW5rIiwgInF1ZXJ5c3RyaW5nRGVjb2RlIiwgImV4dHJhY3RRdWVyeXN0cmluZyIsICJBY3Rpb25Db2RlVVJMIiwgInBhcnNlQWN0aW9uQ29kZVVSTCIsICJFbWFpbEF1dGhQcm92aWRlciIsICJGZWRlcmF0ZWRBdXRoUHJvdmlkZXIiLCAiQmFzZU9BdXRoUHJvdmlkZXIiLCAiT0F1dGhQcm92aWRlciIsICJGYWNlYm9va0F1dGhQcm92aWRlciIsICJHb29nbGVBdXRoUHJvdmlkZXIiLCAiR2l0aHViQXV0aFByb3ZpZGVyIiwgIlNBTUxBdXRoQ3JlZGVudGlhbCIsICJTQU1MX1BST1ZJREVSX1BSRUZJWCIsICJTQU1MQXV0aFByb3ZpZGVyIiwgIlR3aXR0ZXJBdXRoUHJvdmlkZXIiLCAic2lnblVwIiwgIlVzZXJDcmVkZW50aWFsSW1wbCIsICJwcm92aWRlcklkRm9yUmVzcG9uc2UiLCAic2lnbkluQW5vbnltb3VzbHkiLCAiTXVsdGlGYWN0b3JFcnJvciIsICJfcHJvY2Vzc0NyZWRlbnRpYWxTYXZpbmdNZmFDb250ZXh0SWZOZWNlc3NhcnkiLCAicHJvdmlkZXJEYXRhQXNOYW1lcyIsICJ1bmxpbmsiLCAiX2Fzc2VydExpbmtlZFN0YXR1cyIsICJfbGluayIsICJfcmVhdXRoZW50aWNhdGUiLCAiX3NpZ25JbldpdGhDcmVkZW50aWFsIiwgInNpZ25JbldpdGhDcmVkZW50aWFsIiwgImxpbmtXaXRoQ3JlZGVudGlhbCIsICJyZWF1dGhlbnRpY2F0ZVdpdGhDcmVkZW50aWFsIiwgInNpZ25JbldpdGhDdXN0b21Ub2tlbiIsICJnZXRJZFRva2VuUmVzcG9uc2UiLCAiTXVsdGlGYWN0b3JJbmZvSW1wbCIsICJQaG9uZU11bHRpRmFjdG9ySW5mb0ltcGwiLCAiVG90cE11bHRpRmFjdG9ySW5mb0ltcGwiLCAiX3NldEFjdGlvbkNvZGVTZXR0aW5nc09uUmVxdWVzdCIsICJyZWNhY2hlUGFzc3dvcmRQb2xpY3kiLCAiYXV0aGVudGljYXRpb24uc2VuZFBhc3N3b3JkUmVzZXRFbWFpbCIsICJjb25maXJtUGFzc3dvcmRSZXNldCIsICJhY2NvdW50XG4gICAgICAgIC5yZXNldFBhc3N3b3JkIiwgImFjY291bnQuYXBwbHlBY3Rpb25Db2RlIiwgImNoZWNrQWN0aW9uQ29kZSIsICJhY2NvdW50LnJlc2V0UGFzc3dvcmQiLCAidmVyaWZ5UGFzc3dvcmRSZXNldENvZGUiLCAiY3JlYXRlVXNlcldpdGhFbWFpbEFuZFBhc3N3b3JkIiwgInNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkIiwgInJlcXVlc3QiLCAiYWN0aW9uQ29kZVNldHRpbmdzIiwgImFwaS5zZW5kU2lnbkluTGlua1RvRW1haWwiLCAiaXNTaWduSW5XaXRoRW1haWxMaW5rIiwgImNyZWF0ZUF1dGhVcmkiLCAiZmV0Y2hTaWduSW5NZXRob2RzRm9yRW1haWwiLCAiYXBpLnNlbmRFbWFpbFZlcmlmaWNhdGlvbiIsICJ2ZXJpZnlCZWZvcmVVcGRhdGVFbWFpbCIsICJhcGkudmVyaWZ5QW5kQ2hhbmdlRW1haWwiLCAidXBkYXRlUHJvZmlsZSIsICJhcGlVcGRhdGVQcm9maWxlIiwgInVwZGF0ZUVtYWlsIiwgInVwZGF0ZUVtYWlsT3JQYXNzd29yZCIsICJ1cGRhdGVQYXNzd29yZCIsICJhcGlVcGRhdGVFbWFpbFBhc3N3b3JkIiwgIl9mcm9tSWRUb2tlblJlc3BvbnNlIiwgIkdlbmVyaWNBZGRpdGlvbmFsVXNlckluZm8iLCAiRmFjZWJvb2tBZGRpdGlvbmFsVXNlckluZm8iLCAiR2l0aHViQWRkaXRpb25hbFVzZXJJbmZvIiwgIkdvb2dsZUFkZGl0aW9uYWxVc2VySW5mbyIsICJUd2l0dGVyQWRkaXRpb25hbFVzZXJJbmZvIiwgIkZlZGVyYXRlZEFkZGl0aW9uYWxVc2VySW5mb1dpdGhVc2VybmFtZSIsICJnZXRBZGRpdGlvbmFsVXNlckluZm8iLCAic2V0UGVyc2lzdGVuY2UiLCAiaW5pdGlhbGl6ZVJlY2FwdGNoYUNvbmZpZyIsICJ2YWxpZGF0ZVBhc3N3b3JkIiwgIm9uSWRUb2tlbkNoYW5nZWQiLCAiYmVmb3JlQXV0aFN0YXRlQ2hhbmdlZCIsICJvbkF1dGhTdGF0ZUNoYW5nZWQiLCAidXNlRGV2aWNlTGFuZ3VhZ2UiLCAidXBkYXRlQ3VycmVudFVzZXIiLCAic2lnbk91dCIsICJyZXZva2VBY2Nlc3NUb2tlbiIsICJkZWxldGVVc2VyIiwgIk11bHRpRmFjdG9yU2Vzc2lvbkltcGwiLCAiTXVsdGlGYWN0b3JSZXNvbHZlckltcGwiLCAiZ2V0TXVsdGlGYWN0b3JSZXNvbHZlciIsICJzdGFydEVucm9sbFRvdHBNZmEiLCAiZmluYWxpemVFbnJvbGxUb3RwTWZhIiwgIndpdGhkcmF3TWZhIiwgIk11bHRpRmFjdG9yVXNlckltcGwiLCAibXVsdGlGYWN0b3JVc2VyQ2FjaGUiLCAibXVsdGlGYWN0b3IiLCAiQXV0aEludGVyb3AiLCAiZ2V0VmVyc2lvbkZvclBsYXRmb3JtIiwgInJlZ2lzdGVyQXV0aCIsICJfcmVnaXN0ZXJDb21wb25lbnQiLCAiQ29tcG9uZW50IiwgInJlZ2lzdGVyVmVyc2lvbiIsICJ2ZXJzaW9uIiwgImdldEF1dGgiLCAiZ2V0QXBwIiwgImdldERlZmF1bHRFbXVsYXRvckhvc3QiLCAiTk9UX0FWQUlMQUJMRV9FUlJPUiIsICJmYWlsIiwgIkZhaWxDbGFzcyIsICJicm93c2VyTG9jYWxQZXJzaXN0ZW5jZSIsICJicm93c2VyU2Vzc2lvblBlcnNpc3RlbmNlIiwgImJyb3dzZXJDb29raWVQZXJzaXN0ZW5jZSIsICJpbmRleGVkREJMb2NhbFBlcnNpc3RlbmNlIiwgImJyb3dzZXJQb3B1cFJlZGlyZWN0UmVzb2x2ZXIiLCAiUGhvbmVBdXRoUHJvdmlkZXIiLCAicmVhdXRoZW50aWNhdGVXaXRoUGhvbmVOdW1iZXIiLCAidXBkYXRlUGhvbmVOdW1iZXIiLCAic2lnbkluV2l0aFBvcHVwIiwgImxpbmtXaXRoUG9wdXAiLCAicmVhdXRoZW50aWNhdGVXaXRoUG9wdXAiLCAic2lnbkluV2l0aFJlZGlyZWN0IiwgImxpbmtXaXRoUmVkaXJlY3QiLCAicmVhdXRoZW50aWNhdGVXaXRoUmVkaXJlY3QiLCAiZ2V0UmVkaXJlY3RSZXN1bHQiLCAiUmVjYXB0Y2hhVmVyaWZpZXIiLCAiUGhvbmVNdWx0aUZhY3RvckdlbmVyYXRvciIsICJmaW5hbGl6ZVNpZ25JblRvdHBNZmEiLCAiTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsIiwgIlRvdHBNdWx0aUZhY3RvckdlbmVyYXRvciIsICJUb3RwTXVsdGlGYWN0b3JBc3NlcnRpb25JbXBsIiwgIlRvdHBTZWNyZXQiLCAiX2lzRW1wdHlTdHJpbmciLCAiZXhwb3J0cyIsICJyZXF1aXJlX2luZGV4X2NqcyIsICJleHBvcnRzIiwgImF1dGgiLCAiaW1wb3J0X29ic2lkaWFuIiwgImluaXRfZGlzdCIsICJpbXBvcnRfb2JzaWRpYW4iLCAiYXBwIiwgImluaXRfZGlzdCIsICJpbml0X2Rpc3QiLCAidmVyc2lvbiIsICJpbml0X2Rpc3QiLCAiYXBwIiwgIm5hbWUiLCAiaW1wb3J0X29ic2lkaWFuIiwgImFwcCIsICJmdW5jdGlvbnMiLCAiaHR0cHNDYWxsYWJsZSIsICJGaW5nZXJwcmludEpTIiwgImZ1bmN0aW9ucyIsICJodHRwc0NhbGxhYmxlIiwgImF1dGgiLCAic2lnbkluV2l0aEN1c3RvbVRva2VuIiwgIm9uQXV0aFN0YXRlQ2hhbmdlZCJdCn0K