@versatiledatakit/shared
Version:
Versatile Data Kit Shared library enables reusability of shared features like: NgRx Redux, Error Handlers, Utils, Generic Components, etc.
305 lines • 43.8 kB
JavaScript
/*
* Copyright 2023-2025 Broadcom
* SPDX-License-Identifier: Apache-2.0
*/
import { Injectable } from '@angular/core';
import { CollectionsUtil } from '../../../utils';
import { TaurusObject } from '../../../common';
import * as i0 from "@angular/core";
import * as i1 from "../../../core";
import * as i2 from "../../confirmation";
import * as i3 from "ngx-cookie-service";
/**
* ** Url Opener Service that opens internal and external urls depends on provided instructions.
*
* - Utilizes <code>Promise<boolean></code> for communication to invoker that is resolved after navigation.
* - Internal urls could be open directly without confirmation or explicitly with confirmation,
* while external are always prompt for confirmation it there is no option to skip confirmation for next navigations,
* and User prompt such confirmation to be skipped.
* - Skipped confirmation are persisted in Cookie storage as Origin for external urls and as Url for internal urls.
* - Returned Promise is resolved upon navigation ends with true (successful navigation) or false (unsuccessful navigation),
* or rejected with value string if it's on User behalf,
* or if there is some internal handled error it will be rejected with instance of Error and message of the specific problem.
*/
export class UrlOpenerService extends TaurusObject {
/**
* ** Constructor.
*/
constructor(navigationService, confirmationService, cookieService) {
super(UrlOpenerService.CLASS_NAME);
this.navigationService = navigationService;
this.confirmationService = confirmationService;
this.cookieService = cookieService;
/**
* ** Application state, for which origins/urls confirmation should be skipped.
*
* @private
*/
this._skippedOriginsUrlsMap = {};
try {
this._origin = window.location.origin;
this._cookieKey = UrlOpenerService._encodeBase64(UrlOpenerService.CLASS_NAME);
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, cannot identify Cookie key and Origin`);
}
}
/**
* @inheritDoc
*/
open(url, target = '_blank', model = null) {
const _model = { ...(model ?? {}) };
const _nextStep = this._resolveNextStep(url, target);
if (_nextStep.external) {
return this._executeExternalNavigation(url, _model, _nextStep);
}
return this._executeInternalNavigation(url, _model, _nextStep);
}
/**
* ** Initialize service.
*
* - Should be invoked only once.
* - Ideal place for invoking is <code>AppComponent.ngOnInit()</code>.
*/
initialize() {
const extractSkippedOriginsMap = this._extractSkippedUrlsMap();
if (extractSkippedOriginsMap) {
this._skippedOriginsUrlsMap = extractSkippedOriginsMap;
}
}
_resolveNextStep(url, target) {
let newTab = false;
let external = false;
if (target === '_blank') {
newTab = true;
}
if (new RegExp(`^${this._origin}`).test(url)) {
external = false;
}
else if (/^(http|https):\/?\/?/.test(url)) {
external = true;
}
return {
newTab,
external,
sanitizedUrl: url
};
}
_executeExternalNavigation(url, model, nextStep) {
const urlOriginData = this._getExternalUrlOriginData(url);
let confirmationPromise;
if (urlOriginData === '1') {
confirmationPromise = Promise.resolve({ doNotShowFutureConfirmation: false });
}
else {
if (!CollectionsUtil.isStringWithContent(model.title)) {
model.title = `Proceed to <code>${url}</code>`;
}
if (CollectionsUtil.isNil(model.closable)) {
model.closable = true;
}
if (CollectionsUtil.isNil(model.confirmBtnModel)) {
model.confirmBtnModel = {
text: 'Proceed'
};
}
else if (!CollectionsUtil.isStringWithContent(model.confirmBtnModel.text)) {
model.confirmBtnModel.text = 'Proceed';
}
confirmationPromise = this.confirmationService.confirm(model);
}
return confirmationPromise.then((data) => {
if (data.doNotShowFutureConfirmation) {
this._persistSkippedExternalUrlOrigin(url);
}
const isSuccessful = UrlOpenerService._openExternalUrl(nextStep.sanitizedUrl, nextStep.newTab);
if (isSuccessful) {
return true;
}
return Promise.reject(new Error(`${UrlOpenerService.CLASS_NAME}: Exception thrown cannot open external url`));
});
}
_executeInternalNavigation(url, model, nextStep) {
const urlData = this._getInternalUrlData(url);
let confirmationPromise;
if (urlData === '1' || !model.explicitConfirmation) {
confirmationPromise = Promise.resolve({ doNotShowFutureConfirmation: false });
}
else {
if (!CollectionsUtil.isStringWithContent(model.title)) {
model.title = `Proceed to <code>${url}</code>`;
}
if (CollectionsUtil.isNil(model.confirmBtnModel)) {
model.confirmBtnModel = {
text: 'Proceed'
};
}
else if (!CollectionsUtil.isStringWithContent(model.confirmBtnModel.text)) {
model.confirmBtnModel.text = 'Proceed';
}
confirmationPromise = this.confirmationService.confirm(model);
}
return confirmationPromise.then((data) => {
if (data.doNotShowFutureConfirmation) {
this._persistSkippedInternalUrl(url);
}
if (nextStep.newTab) {
const isSuccessful = UrlOpenerService._openExternalUrl(nextStep.sanitizedUrl, true);
if (isSuccessful) {
return true;
}
return Promise.reject(new Error(`${UrlOpenerService.CLASS_NAME}: Exception thrown, cannot open Super Collider url in a new tab`));
}
const _queryParams = {};
let _sanitizedUrl = nextStep.sanitizedUrl;
try {
const queryStringStartIndex = url.indexOf('?');
if (queryStringStartIndex !== -1) {
_sanitizedUrl = url.substring(0, queryStringStartIndex);
const queryString = url.substring(queryStringStartIndex);
new URLSearchParams(queryString).forEach((value, key) => {
_queryParams[key] = value;
});
}
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, Exception thrown while extracting query string for internal navigation`);
}
return this.navigationService.navigate(_sanitizedUrl, { queryParams: _queryParams });
});
}
_getExternalUrlOriginData(url) {
const urlOrigin = UrlOpenerService._getUrlOrigin(url);
if (!this._skippedOriginsUrlsMap[urlOrigin]) {
return null;
}
return this._skippedOriginsUrlsMap[urlOrigin];
}
_persistSkippedExternalUrlOrigin(url) {
const urlOrigin = UrlOpenerService._getUrlOrigin(url);
if (!urlOrigin) {
return;
}
this._persistSkippedInternalUrl(urlOrigin);
}
_getInternalUrlData(url) {
if (!this._skippedOriginsUrlsMap[url]) {
return null;
}
return this._skippedOriginsUrlsMap[url];
}
_persistSkippedInternalUrl(url) {
if (this._skippedOriginsUrlsMap[url]) {
return;
}
this._skippedOriginsUrlsMap[url] = '1';
this._persistSkippedUrlsMap();
}
_extractSkippedUrlsMap() {
const extractedOriginsMap = this.cookieService.get(this._cookieKey);
if (!extractedOriginsMap) {
return null;
}
const decodedOriginsMap = UrlOpenerService._decodeBase64(extractedOriginsMap);
if (!decodedOriginsMap) {
return null;
}
const parsedOriginsMap = UrlOpenerService._parseToJSON(decodedOriginsMap);
if (!parsedOriginsMap) {
return null;
}
return parsedOriginsMap;
}
_persistSkippedUrlsMap() {
if (!this._skippedOriginsUrlsMap) {
return;
}
const serializedOriginsMap = UrlOpenerService._serializeObject(this._skippedOriginsUrlsMap);
if (!serializedOriginsMap) {
return;
}
const encodedOriginsMap = UrlOpenerService._encodeBase64(serializedOriginsMap);
if (!encodedOriginsMap) {
return;
}
this.cookieService.set(this._cookieKey, encodedOriginsMap);
}
static _openExternalUrl(url, newTab) {
try {
window.open(url, newTab ? '_blank' : '_self', 'noopener');
return true;
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Cannot open external url, check your Browser security config if allows opening new tabs`);
return false;
}
}
static _getUrlOrigin(url) {
try {
const _url = new URL(url);
return _url.origin;
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, cannot extract origin from url`);
return null;
}
}
static _encodeBase64(value) {
if (!value) {
return null;
}
try {
return btoa(value);
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, provided value cannot be encoded to base64`);
return null;
}
}
static _decodeBase64(value) {
if (!value) {
return null;
}
try {
return atob(value);
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, provided value cannot be decoded from base64`);
return null;
}
}
static _serializeObject(value) {
if (!value) {
return null;
}
try {
return JSON.stringify(value);
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, cannot serialize provided object`);
return null;
}
}
static _parseToJSON(value) {
if (!value) {
return null;
}
try {
return JSON.parse(value);
}
catch (e) {
console.error(`${UrlOpenerService.CLASS_NAME}: Potential bug found, cannot parse provided JSON`);
return null;
}
}
}
/**
* @inheritDoc
*/
UrlOpenerService.CLASS_NAME = 'UrlOpenerService';
UrlOpenerService.ɵfac = function UrlOpenerService_Factory(t) { return new (t || UrlOpenerService)(i0.ɵɵinject(i1.NavigationService), i0.ɵɵinject(i2.ConfirmationService), i0.ɵɵinject(i3.CookieService)); };
UrlOpenerService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: UrlOpenerService, factory: UrlOpenerService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UrlOpenerService, [{
type: Injectable
}], function () { return [{ type: i1.NavigationService }, { type: i2.ConfirmationService }, { type: i3.CookieService }]; }, null); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXJsLW9wZW5lci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hhcmVkL3NyYy9saWIvZmVhdHVyZXMvdXJsLW9wZW5lci9zZXJ2aWNlcy91cmwtb3BlbmVyLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUszQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFakQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7OztBQTRCL0M7Ozs7Ozs7Ozs7O0dBV0c7QUFFSCxNQUFNLE9BQU8sZ0JBQWlCLFNBQVEsWUFBWTtJQTZCOUM7O09BRUc7SUFDSCxZQUNxQixpQkFBb0MsRUFDcEMsbUJBQXdDLEVBQ3hDLGFBQTRCO1FBRTdDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUpsQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ3BDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFDeEMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFiakQ7Ozs7V0FJRztRQUNLLDJCQUFzQixHQUF3QixFQUFFLENBQUM7UUFZckQsSUFBSTtZQUNBLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7WUFDdEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDakY7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLDhEQUE4RCxDQUFDLENBQUM7U0FDL0c7SUFDTCxDQUFDO0lBa0NEOztPQUVHO0lBQ0gsSUFBSSxDQUFDLEdBQVcsRUFBRSxTQUEwQixRQUFRLEVBQUUsUUFBd0IsSUFBSTtRQUM5RSxNQUFNLE1BQU0sR0FBbUIsRUFBRSxHQUFHLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxFQUFvQixDQUFDO1FBQ3RFLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFckQsSUFBSSxTQUFTLENBQUMsUUFBUSxFQUFFO1lBQ3BCLE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7U0FDbEU7UUFFRCxPQUFPLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ25FLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILFVBQVU7UUFDTixNQUFNLHdCQUF3QixHQUFHLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQy9ELElBQUksd0JBQXdCLEVBQUU7WUFDMUIsSUFBSSxDQUFDLHNCQUFzQixHQUFHLHdCQUF3QixDQUFDO1NBQzFEO0lBQ0wsQ0FBQztJQUVPLGdCQUFnQixDQUFDLEdBQVcsRUFBRSxNQUF1QjtRQUN6RCxJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBRXJCLElBQUksTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUNyQixNQUFNLEdBQUcsSUFBSSxDQUFDO1NBQ2pCO1FBRUQsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUMxQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1NBQ3BCO2FBQU0sSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDekMsUUFBUSxHQUFHLElBQUksQ0FBQztTQUNuQjtRQUVELE9BQU87WUFDSCxNQUFNO1lBQ04sUUFBUTtZQUNSLFlBQVksRUFBRSxHQUFHO1NBQ3BCLENBQUM7SUFDTixDQUFDO0lBRU8sMEJBQTBCLENBQUMsR0FBVyxFQUFFLEtBQXFCLEVBQUUsUUFBdUI7UUFDMUYsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRTFELElBQUksbUJBQXFELENBQUM7UUFFMUQsSUFBSSxhQUFhLEtBQUssR0FBRyxFQUFFO1lBQ3ZCLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSwyQkFBMkIsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1NBQ2pGO2FBQU07WUFDSCxJQUFJLENBQUMsZUFBZSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDbkQsS0FBSyxDQUFDLEtBQUssR0FBRyxvQkFBb0IsR0FBRyxTQUFTLENBQUM7YUFDbEQ7WUFFRCxJQUFJLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUN2QyxLQUFLLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQzthQUN6QjtZQUVELElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQUU7Z0JBQzlDLEtBQUssQ0FBQyxlQUFlLEdBQUc7b0JBQ3BCLElBQUksRUFBRSxTQUFTO2lCQUNsQixDQUFDO2FBQ0w7aUJBQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUN6RSxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksR0FBRyxTQUFTLENBQUM7YUFDMUM7WUFFRCxtQkFBbUIsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ2pFO1FBRUQsT0FBTyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNyQyxJQUFJLElBQUksQ0FBQywyQkFBMkIsRUFBRTtnQkFDbEMsSUFBSSxDQUFDLGdDQUFnQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQzlDO1lBRUQsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0YsSUFBSSxZQUFZLEVBQUU7Z0JBQ2QsT0FBTyxJQUFJLENBQUM7YUFDZjtZQUVELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxHQUFHLGdCQUFnQixDQUFDLFVBQVUsNkNBQTZDLENBQUMsQ0FBQyxDQUFDO1FBQ2xILENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLDBCQUEwQixDQUFDLEdBQVcsRUFBRSxLQUFxQixFQUFFLFFBQXVCO1FBQzFGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU5QyxJQUFJLG1CQUFxRCxDQUFDO1FBRTFELElBQUksT0FBTyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRTtZQUNoRCxtQkFBbUIsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsMkJBQTJCLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztTQUNqRjthQUFNO1lBQ0gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ25ELEtBQUssQ0FBQyxLQUFLLEdBQUcsb0JBQW9CLEdBQUcsU0FBUyxDQUFDO2FBQ2xEO1lBRUQsSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRTtnQkFDOUMsS0FBSyxDQUFDLGVBQWUsR0FBRztvQkFDcEIsSUFBSSxFQUFFLFNBQVM7aUJBQ2xCLENBQUM7YUFDTDtpQkFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3pFLEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBSSxHQUFHLFNBQVMsQ0FBQzthQUMxQztZQUVELG1CQUFtQixHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDakU7UUFFRCxPQUFPLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3JDLElBQUksSUFBSSxDQUFDLDJCQUEyQixFQUFFO2dCQUNsQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDeEM7WUFFRCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUU7Z0JBQ2pCLE1BQU0sWUFBWSxHQUFHLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3BGLElBQUksWUFBWSxFQUFFO29CQUNkLE9BQU8sSUFBSSxDQUFDO2lCQUNmO2dCQUVELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FDakIsSUFBSSxLQUFLLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLGlFQUFpRSxDQUFDLENBQzdHLENBQUM7YUFDTDtZQUVELE1BQU0sWUFBWSxHQUFXLEVBQUUsQ0FBQztZQUNoQyxJQUFJLGFBQWEsR0FBVyxRQUFRLENBQUMsWUFBWSxDQUFDO1lBRWxELElBQUk7Z0JBQ0EsTUFBTSxxQkFBcUIsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUUvQyxJQUFJLHFCQUFxQixLQUFLLENBQUMsQ0FBQyxFQUFFO29CQUM5QixhQUFhLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUscUJBQXFCLENBQUMsQ0FBQztvQkFDeEQsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO29CQUN6RCxJQUFJLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUU7d0JBQ3BELFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7b0JBQzlCLENBQUMsQ0FBQyxDQUFDO2lCQUNOO2FBQ0o7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDUixPQUFPLENBQUMsS0FBSyxDQUNULEdBQUcsZ0JBQWdCLENBQUMsVUFBVSwrRkFBK0YsQ0FDaEksQ0FBQzthQUNMO1lBRUQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBQ3pGLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLHlCQUF5QixDQUFDLEdBQVc7UUFDekMsTUFBTSxTQUFTLEdBQUcsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXRELElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLEVBQUU7WUFDekMsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFTyxnQ0FBZ0MsQ0FBQyxHQUFXO1FBQ2hELE1BQU0sU0FBUyxHQUFHLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUV0RCxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ1osT0FBTztTQUNWO1FBRUQsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxHQUFXO1FBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDbkMsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFTywwQkFBMEIsQ0FBQyxHQUFXO1FBQzFDLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ2xDLE9BQU87U0FDVjtRQUVELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUM7UUFFdkMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7SUFDbEMsQ0FBQztJQUVPLHNCQUFzQjtRQUMxQixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNwRSxJQUFJLENBQUMsbUJBQW1CLEVBQUU7WUFDdEIsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELE1BQU0saUJBQWlCLEdBQUcsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDOUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFO1lBQ3BCLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFFRCxNQUFNLGdCQUFnQixHQUFHLGdCQUFnQixDQUFDLFlBQVksQ0FBc0IsaUJBQWlCLENBQUMsQ0FBQztRQUMvRixJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDbkIsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELE9BQU8sZ0JBQWdCLENBQUM7SUFDNUIsQ0FBQztJQUVPLHNCQUFzQjtRQUMxQixJQUFJLENBQUMsSUFBSSxDQUFDLHNCQUFzQixFQUFFO1lBQzlCLE9BQU87U0FDVjtRQUVELE1BQU0sb0JBQW9CLEdBQUcsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFDNUYsSUFBSSxDQUFDLG9CQUFvQixFQUFFO1lBQ3ZCLE9BQU87U0FDVjtRQUVELE1BQU0saUJBQWlCLEdBQUcsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLGlCQUFpQixFQUFFO1lBQ3BCLE9BQU87U0FDVjtRQUVELElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBRU8sTUFBTSxDQUFDLGdCQUFnQixDQUFDLEdBQVcsRUFBRSxNQUFlO1FBQ3hELElBQUk7WUFDQSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBRTFELE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQ1QsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLDJGQUEyRixDQUM1SCxDQUFDO1lBRUYsT0FBTyxLQUFLLENBQUM7U0FDaEI7SUFDTCxDQUFDO0lBRU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxHQUFXO1FBQ3BDLElBQUk7WUFDQSxNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUxQixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7U0FDdEI7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLHVEQUF1RCxDQUFDLENBQUM7WUFFckcsT0FBTyxJQUFJLENBQUM7U0FDZjtJQUNMLENBQUM7SUFFTyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQWE7UUFDdEMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNSLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFFRCxJQUFJO1lBQ0EsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDdEI7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLG1FQUFtRSxDQUFDLENBQUM7WUFFakgsT0FBTyxJQUFJLENBQUM7U0FDZjtJQUNMLENBQUM7SUFFTyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQWE7UUFDdEMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNSLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFFRCxJQUFJO1lBQ0EsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDdEI7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLHFFQUFxRSxDQUFDLENBQUM7WUFFbkgsT0FBTyxJQUFJLENBQUM7U0FDZjtJQUNMLENBQUM7SUFFTyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsS0FBYztRQUMxQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1IsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUVELElBQUk7WUFDQSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDaEM7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxVQUFVLHlEQUF5RCxDQUFDLENBQUM7WUFFdkcsT0FBTyxJQUFJLENBQUM7U0FDZjtJQUNMLENBQUM7SUFFTyxNQUFNLENBQUMsWUFBWSxDQUFJLEtBQWE7UUFDeEMsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNSLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFFRCxJQUFJO1lBQ0EsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBTSxDQUFDO1NBQ2pDO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDUixPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsVUFBVSxtREFBbUQsQ0FBQyxDQUFDO1lBRWpHLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7SUFDTCxDQUFDOztBQWhZRDs7R0FFRztBQUNzQiwyQkFBVSxHQUFXLGtCQUFtQixDQUFBO2dGQUp4RCxnQkFBZ0I7c0VBQWhCLGdCQUFnQixXQUFoQixnQkFBZ0I7dUZBQWhCLGdCQUFnQjtjQUQ1QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDIzLTIwMjUgQnJvYWRjb21cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUGFyYW1zIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcblxuaW1wb3J0IHsgQ29va2llU2VydmljZSB9IGZyb20gJ25neC1jb29raWUtc2VydmljZSc7XG5cbmltcG9ydCB7IENvbGxlY3Rpb25zVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWxzJztcblxuaW1wb3J0IHsgVGF1cnVzT2JqZWN0IH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uJztcblxuaW1wb3J0IHsgTmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9jb3JlJztcblxuaW1wb3J0IHsgQ29uZmlybWF0aW9uT3V0cHV0TW9kZWwsIENvbmZpcm1hdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb25maXJtYXRpb24nO1xuXG5pbXBvcnQgeyBVcmxPcGVuZXJNb2RlbCwgVXJsT3BlbmVyVGFyZ2V0IH0gZnJvbSAnLi4vbW9kZWwnO1xuXG4vKipcbiAqICoqIEludGVybmFsIHNlcnZpY2UgbW9kZWwuXG4gKi9cbmludGVyZmFjZSBOZXh0U3RlcE1vZGVsIHtcbiAgICAvKipcbiAgICAgKiAqKiBJcyBwcm92aWRlZCB1cmwgZXh0ZXJuYWwuXG4gICAgICovXG4gICAgZXh0ZXJuYWw6IGJvb2xlYW47XG4gICAgLyoqXG4gICAgICogKiogU2FuaXRpemVkIHVybC5cbiAgICAgKlxuICAgICAqICAgICAgLSBDb3VsZCBiZSB1c2UgaW4gZnV0dXJlIGlmIHNvbWUgc2FuaXRpemF0aW9uIGlzIG5lZWRlZCBmb3Igc29tZSBzcGVjaWFsIGNhc2VzLlxuICAgICAqL1xuICAgIHNhbml0aXplZFVybDogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqICoqIERvZXMgdXJsIGJlIG9wZW4gaW4gbmV3IHRhYi5cbiAgICAgKi9cbiAgICBuZXdUYWI6IGJvb2xlYW47XG59XG5cbi8qKlxuICogKiogVXJsIE9wZW5lciBTZXJ2aWNlIHRoYXQgb3BlbnMgaW50ZXJuYWwgYW5kIGV4dGVybmFsIHVybHMgZGVwZW5kcyBvbiBwcm92aWRlZCBpbnN0cnVjdGlvbnMuXG4gKlxuICogICAgICAtIFV0aWxpemVzIDxjb2RlPlByb21pc2U8Ym9vbGVhbj48L2NvZGU+IGZvciBjb21tdW5pY2F0aW9uIHRvIGludm9rZXIgdGhhdCBpcyByZXNvbHZlZCBhZnRlciBuYXZpZ2F0aW9uLlxuICogICAgICAtIEludGVybmFsIHVybHMgY291bGQgYmUgb3BlbiBkaXJlY3RseSB3aXRob3V0IGNvbmZpcm1hdGlvbiBvciBleHBsaWNpdGx5IHdpdGggY29uZmlybWF0aW9uLFxuICogICAgICAgICAgICAgIHdoaWxlIGV4dGVybmFsIGFyZSBhbHdheXMgcHJvbXB0IGZvciBjb25maXJtYXRpb24gaXQgdGhlcmUgaXMgbm8gb3B0aW9uIHRvIHNraXAgY29uZmlybWF0aW9uIGZvciBuZXh0IG5hdmlnYXRpb25zLFxuICogICAgICAgICAgICAgIGFuZCBVc2VyIHByb21wdCBzdWNoIGNvbmZpcm1hdGlvbiB0byBiZSBza2lwcGVkLlxuICogICAgICAtIFNraXBwZWQgY29uZmlybWF0aW9uIGFyZSBwZXJzaXN0ZWQgaW4gQ29va2llIHN0b3JhZ2UgYXMgT3JpZ2luIGZvciBleHRlcm5hbCB1cmxzIGFuZCBhcyBVcmwgZm9yIGludGVybmFsIHVybHMuXG4gKiAgICAgIC0gUmV0dXJuZWQgUHJvbWlzZSBpcyByZXNvbHZlZCB1cG9uIG5hdmlnYXRpb24gZW5kcyB3aXRoIHRydWUgKHN1Y2Nlc3NmdWwgbmF2aWdhdGlvbikgb3IgZmFsc2UgKHVuc3VjY2Vzc2Z1bCBuYXZpZ2F0aW9uKSxcbiAqICAgICAgICAgICAgICBvciByZWplY3RlZCB3aXRoIHZhbHVlIHN0cmluZyBpZiBpdCdzIG9uIFVzZXIgYmVoYWxmLFxuICogICAgICAgICAgICAgIG9yIGlmIHRoZXJlIGlzIHNvbWUgaW50ZXJuYWwgaGFuZGxlZCBlcnJvciBpdCB3aWxsIGJlIHJlamVjdGVkIHdpdGggaW5zdGFuY2Ugb2YgRXJyb3IgYW5kIG1lc3NhZ2Ugb2YgdGhlIHNwZWNpZmljIHByb2JsZW0uXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBVcmxPcGVuZXJTZXJ2aWNlIGV4dGVuZHMgVGF1cnVzT2JqZWN0IHtcbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdERvY1xuICAgICAqL1xuICAgIHN0YXRpYyBvdmVycmlkZSByZWFkb25seSBDTEFTU19OQU1FOiBzdHJpbmcgPSAnVXJsT3BlbmVyU2VydmljZSc7XG5cbiAgICAvKipcbiAgICAgKiAqKiBBcHBsaWNhdGlvbiBvcmlnaW4sIHJlc29sdmVkIHVwb24gc2VydmljZSBkZWNsYXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfb3JpZ2luOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiAqKiBDb29raWUga2V5IHdoZXJlIHNlcnZpY2Ugc3RhdGUgaXMgcGVyc2lzdGVkLCByZXNvbHZlZCB1cG9uIHNlcnZpY2UgZGVjbGFyYXRpb24uXG4gICAgICpcbiAgICAgKiAgICAgIC0gSXQncyBzZXJ2aWNlIENsYXNzIE5hbWUgZW5jb2RlZCB0byBCYXNlNjQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2Nvb2tpZUtleTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogKiogQXBwbGljYXRpb24gc3RhdGUsIGZvciB3aGljaCBvcmlnaW5zL3VybHMgY29uZmlybWF0aW9uIHNob3VsZCBiZSBza2lwcGVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBwcml2YXRlIF9za2lwcGVkT3JpZ2luc1VybHNNYXA6IFJlY29yZDxzdHJpbmcsICcxJz4gPSB7fTtcblxuICAgIC8qKlxuICAgICAqICoqIENvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IG5hdmlnYXRpb25TZXJ2aWNlOiBOYXZpZ2F0aW9uU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBjb25maXJtYXRpb25TZXJ2aWNlOiBDb25maXJtYXRpb25TZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGNvb2tpZVNlcnZpY2U6IENvb2tpZVNlcnZpY2VcbiAgICApIHtcbiAgICAgICAgc3VwZXIoVXJsT3BlbmVyU2VydmljZS5DTEFTU19OQU1FKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhpcy5fb3JpZ2luID0gd2luZG93LmxvY2F0aW9uLm9yaWdpbjtcbiAgICAgICAgICAgIHRoaXMuX2Nvb2tpZUtleSA9IFVybE9wZW5lclNlcnZpY2UuX2VuY29kZUJhc2U2NChVcmxPcGVuZXJTZXJ2aWNlLkNMQVNTX05BTUUpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGAke1VybE9wZW5lclNlcnZpY2UuQ0xBU1NfTkFNRX06IFBvdGVudGlhbCBidWcgZm91bmQsIGNhbm5vdCBpZGVudGlmeSBDb29raWUga2V5IGFuZCBPcmlnaW5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqICoqIE9wZW4gcHJvdmlkZWQgVXJsIHRvIGRlZmF1bHQgX2JsYW5rIHRhcmdldC5cbiAgICAgKlxuICAgICAqICAgICAgLSBJbnRlcm5hbCB1cmxzIGFyZSBvcGVuIGRpcmVjdGx5IHdpdGhvdXQgY29uZmlybWF0aW9uLCB3aGlsZSBleHRlcm5hbCBhcmUgYWx3YXlzIHByb21wdCBmb3IgY29uZmlybWF0aW9uLlxuICAgICAqICAgICAgLSBSZXR1cm5lZCBQcm9taXNlIGlzIHJlc29sdmVkIHVwb24gbmF2aWdhdGlvbiBlbmRzIHdpdGggdHJ1ZSAoc3VjY2Vzc2Z1bCBuYXZpZ2F0aW9uKSBvciBmYWxzZSAodW5zdWNjZXNzZnVsIG5hdmlnYXRpb24pLFxuICAgICAqICAgICAgICAgICAgICBvciBpZiB0aGVyZSBpcyBzb21lIGludGVybmFsIGhhbmRsZWQgZXJyb3IgaXQgd2lsbCBiZSByZWplY3RlZCB3aXRoIGluc3RhbmNlIG9mIEVycm9yIGFuZCBtZXNzYWdlIG9mIHRoZSBzcGVjaWZpYyBwcm9ibGVtLlxuICAgICAqICAgICAgLSBFdmVyeSB1cmwgd2hpY2ggc3RhcnRzIHdpdGggcGF0dGVybiBodHRwOi8vIG9yIGh0dHBzOi8vIGFuZCBpdHMgb3JpZ2luIGlzIGRpZmZlcmVudCBmcm9tIEFwcGxpY2F0aW9uIG9yaWdpbiBpcyBtYXJrZWQgYXMgZXh0ZXJuYWwgdXJsLlxuICAgICAqICAgICAgLSBFdmVyeXRoaW5nIGVsc2UgaXMgaW50ZXJuYWwgdXJsLlxuICAgICAqL1xuICAgIG9wZW4odXJsOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIC8qKlxuICAgICAqICoqIE9wZW4gcHJvdmlkZWQgVXJsIHVzaW5nIHByb3ZpZGVkIHRhcmdldCBfc2VsZiBvciBfYmxhbmtcbiAgICAgKlxuICAgICAqICAgICAgLSBJbnRlcm5hbCB1cmxzIGFyZSBvcGVuIGRpcmVjdGx5IHdpdGhvdXQgY29uZmlybWF0aW9uLCB3aGlsZSBleHRlcm5hbCBhcmUgYWx3YXlzIHByb21wdCBmb3IgY29uZmlybWF0aW9uLlxuICAgICAqICAgICAgLSBSZXR1cm5lZCBQcm9taXNlIGlzIHJlc29sdmVkIHVwb24gbmF2aWdhdGlvbiBlbmRzIHdpdGggdHJ1ZSAoc3VjY2Vzc2Z1bCBuYXZpZ2F0aW9uKSBvciBmYWxzZSAodW5zdWNjZXNzZnVsIG5hdmlnYXRpb24pLFxuICAgICAqICAgICAgICAgICAgICBvciBpZiB0aGVyZSBpcyBzb21lIGludGVybmFsIGhhbmRsZWQgZXJyb3IgaXQgd2lsbCBiZSByZWplY3RlZCB3aXRoIGluc3RhbmNlIG9mIEVycm9yIGFuZCBtZXNzYWdlIG9mIHRoZSBzcGVjaWZpYyBwcm9ibGVtLlxuICAgICAqICAgICAgLSBFdmVyeSB1cmwgd2hpY2ggc3RhcnRzIHdpdGggcGF0dGVybiBodHRwOi8vIG9yIGh0dHBzOi8vIGFuZCBpdHMgb3JpZ2luIGlzIGRpZmZlcmVudCBmcm9tIEFwcGxpY2F0aW9uIG9yaWdpbiBpcyBtYXJrZWQgYXMgZXh0ZXJuYWwgdXJsLlxuICAgICAqICAgICAgLSBFdmVyeXRoaW5nIGVsc2UgaXMgaW50ZXJuYWwgdXJsLlxuICAgICAqL1xuICAgIG9wZW4odXJsOiBzdHJpbmcsIHRhcmdldDogVXJsT3BlbmVyVGFyZ2V0KTogUHJvbWlzZTxib29sZWFuPjtcbiAgICAvKipcbiAgICAgKiAqKiBPcGVuIHByb3ZpZGVkIFVybCB1c2luZyBwcm92aWRlZCB0YXJnZXQgX3NlbGYgb3IgX2JsYW5rIGFuZCB1dGlsaXppbmcgcHJvdmlkZWQgbW9kZWwgYW5kIHNlcnZpY2Ugd2lsbCBzZXQgc29tZSBkZWZhdWx0cyBmb3Igb3B0aW9uYWwgZmllbGRzLlxuICAgICAqXG4gICAgICogICAgICAtIEludGVybmFsIHVybHMgY291bGQgYmUgb3BlbiBkaXJlY3RseSB3aXRob3V0IGNvbmZpcm1hdGlvbiBvciBleHBsaWNpdGx5IHdpdGggY29uZmlybWF0aW9uIGRlcGVuZCBvbiBwcm92aWRlZCBtb2RlbCxcbiAgICAgKiAgICAgICAgICAgICAgd2hpbGUgZXh0ZXJuYWwgYXJlIGFsd2F5cyBwcm9tcHQgZm9yIGNvbmZpcm1hdGlvbiBpdCB0aGVyZSBpcyBubyBvcHRpb24gdG8gc2tpcCBjb25maXJtYXRpb24gZm9yIG5leHQgbmF2aWdhdGlvbnMsXG4gICAgICogICAgICAgICAgICAgIGFuZCBVc2VyIHByb21wdCBzdWNoIGNvbmZpcm1hdGlvbiB0byBiZSBza2lwcGVkLlxuICAgICAqICAgICAgLSBTa2lwcGVkIGNvbmZpcm1hdGlvbiBhcmUgcGVyc2lzdGVkIGluIENvb2tpZSBzdG9yYWdlIGFzIE9yaWdpbiBmb3IgZXh0ZXJuYWwgdXJscyBhbmQgYXMgVXJsIGZvciBpbnRlcm5hbCB1cmxzLlxuICAgICAqICAgICAgLSBSZXR1cm5lZCBQcm9taXNlIGlzIHJlc29sdmVkIHVwb24gbmF2aWdhdGlvbiBlbmRzIHdpdGggdHJ1ZSAoc3VjY2Vzc2Z1bCBuYXZpZ2F0aW9uKSBvciBmYWxzZSAodW5zdWNjZXNzZnVsIG5hdmlnYXRpb24pLFxuICAgICAqICAgICAgICAgICAgICBvciByZWplY3RlZCB3aXRoIHZhbHVlIHN0cmluZyBpZiBpdCdzIG9uIFVzZXIgYmVoYWxmIHdoZW4gY29uZmlybWF0aW9uIGlzIGNsb3NhYmxlIG9yIHdpdGggYnV0dG9uIGNhbmNlbCxcbiAgICAgKiAgICAgICAgICAgICAgb3IgaWYgdGhlcmUgaXMgc29tZSBpbnRlcm5hbCBoYW5kbGVkIGVycm9yIGl0IHdpbGwgYmUgcmVqZWN0ZWQgd2l0aCBpbnN0YW5jZSBvZiBFcnJvciBhbmQgbWVzc2FnZSBvZiB0aGUgc3BlY2lmaWMgcHJvYmxlbS5cbiAgICAgKi9cbiAgICBvcGVuKHVybDogc3RyaW5nLCB0YXJnZXQ6IFVybE9wZW5lclRhcmdldCwgbW9kZWw6IFVybE9wZW5lck1vZGVsKTogUHJvbWlzZTxib29sZWFuPjtcbiAgICAvKipcbiAgICAgKiBAaW5oZXJpdERvY1xuICAgICAqL1xuICAgIG9wZW4odXJsOiBzdHJpbmcsIHRhcmdldDogVXJsT3BlbmVyVGFyZ2V0ID0gJ19ibGFuaycsIG1vZGVsOiBVcmxPcGVuZXJNb2RlbCA9IG51bGwpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgX21vZGVsOiBVcmxPcGVuZXJNb2RlbCA9IHsgLi4uKG1vZGVsID8/IHt9KSB9IGFzIFVybE9wZW5lck1vZGVsO1xuICAgICAgICBjb25zdCBfbmV4dFN0ZXAgPSB0aGlzLl9yZXNvbHZlTmV4dFN0ZXAodXJsLCB0YXJnZXQpO1xuXG4gICAgICAgIGlmIChfbmV4dFN0ZXAuZXh0ZXJuYWwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9leGVjdXRlRXh0ZXJuYWxOYXZpZ2F0aW9uKHVybCwgX21vZGVsLCBfbmV4dFN0ZXApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2V4ZWN1dGVJbnRlcm5hbE5hdmlnYXRpb24odXJsLCBfbW9kZWwsIF9uZXh0U3RlcCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogSW5pdGlhbGl6ZSBzZXJ2aWNlLlxuICAgICAqXG4gICAgICogICAgICAtIFNob3VsZCBiZSBpbnZva2VkIG9ubHkgb25jZS5cbiAgICAgKiAgICAgIC0gSWRlYWwgcGxhY2UgZm9yIGludm9raW5nIGlzIDxjb2RlPkFwcENvbXBvbmVudC5uZ09uSW5pdCgpPC9jb2RlPi5cbiAgICAgKi9cbiAgICBpbml0aWFsaXplKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBleHRyYWN0U2tpcHBlZE9yaWdpbnNNYXAgPSB0aGlzLl9leHRyYWN0U2tpcHBlZFVybHNNYXAoKTtcbiAgICAgICAgaWYgKGV4dHJhY3RTa2lwcGVkT3JpZ2luc01hcCkge1xuICAgICAgICAgICAgdGhpcy5fc2tpcHBlZE9yaWdpbnNVcmxzTWFwID0gZXh0cmFjdFNraXBwZWRPcmlnaW5zTWFwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcmVzb2x2ZU5leHRTdGVwKHVybDogc3RyaW5nLCB0YXJnZXQ6IFVybE9wZW5lclRhcmdldCk6IE5leHRTdGVwTW9kZWwge1xuICAgICAgICBsZXQgbmV3VGFiID0gZmFsc2U7XG4gICAgICAgIGxldCBleHRlcm5hbCA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh0YXJnZXQgPT09ICdfYmxhbmsnKSB7XG4gICAgICAgICAgICBuZXdUYWIgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG5ldyBSZWdFeHAoYF4ke3RoaXMuX29yaWdpbn1gKS50ZXN0KHVybCkpIHtcbiAgICAgICAgICAgIGV4dGVybmFsID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAoL14oaHR0cHxodHRwcyk6XFwvP1xcLz8vLnRlc3QodXJsKSkge1xuICAgICAgICAgICAgZXh0ZXJuYWwgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5ld1RhYixcbiAgICAgICAgICAgIGV4dGVybmFsLFxuICAgICAgICAgICAgc2FuaXRpemVkVXJsOiB1cmxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9leGVjdXRlRXh0ZXJuYWxOYXZpZ2F0aW9uKHVybDogc3RyaW5nLCBtb2RlbDogVXJsT3BlbmVyTW9kZWwsIG5leHRTdGVwOiBOZXh0U3RlcE1vZGVsKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIGNvbnN0IHVybE9yaWdpbkRhdGEgPSB0aGlzLl9nZXRFeHRlcm5hbFVybE9yaWdpbkRhdGEodXJsKTtcblxuICAgICAgICBsZXQgY29uZmlybWF0aW9uUHJvbWlzZTogUHJvbWlzZTxDb25maXJtYXRpb25PdXRwdXRNb2RlbD47XG5cbiAgICAgICAgaWYgKHVybE9yaWdpbkRhdGEgPT09ICcxJykge1xuICAgICAgICAgICAgY29uZmlybWF0aW9uUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSh7IGRvTm90U2hvd0Z1dHVyZUNvbmZpcm1hdGlvbjogZmFsc2UgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIUNvbGxlY3Rpb25zVXRpbC5pc1N0cmluZ1dpdGhDb250ZW50KG1vZGVsLnRpdGxlKSkge1xuICAgICAgICAgICAgICAgIG1vZGVsLnRpdGxlID0gYFByb2NlZWQgdG8gPGNvZGU+JHt1cmx9PC9jb2RlPmA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChDb2xsZWN0aW9uc1V0aWwuaXNOaWwobW9kZWwuY2xvc2FibGUpKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwuY2xvc2FibGUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoQ29sbGVjdGlvbnNVdGlsLmlzTmlsKG1vZGVsLmNvbmZpcm1CdG5Nb2RlbCkpIHtcbiAgICAgICAgICAgICAgICBtb2RlbC5jb25maXJtQnRuTW9kZWwgPSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHQ6ICdQcm9jZWVkJ1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFDb2xsZWN0aW9uc1V0aWwuaXNTdHJpbmdXaXRoQ29udGVudChtb2RlbC5jb25maXJtQnRuTW9kZWwudGV4dCkpIHtcbiAgICAgICAgICAgICAgICBtb2RlbC5jb25maXJtQnRuTW9kZWwudGV4dCA9ICdQcm9jZWVkJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uZmlybWF0aW9uUHJvbWlzZSA9IHRoaXMuY29uZmlybWF0aW9uU2VydmljZS5jb25maXJtKG1vZGVsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb25maXJtYXRpb25Qcm9taXNlLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgICAgICAgIGlmIChkYXRhLmRvTm90U2hvd0Z1dHVyZUNvbmZpcm1hdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3BlcnNpc3RTa2lwcGVkRXh0ZXJuYWxVcmxPcmlnaW4odXJsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgaXNTdWNjZXNzZnVsID0gVXJsT3BlbmVyU2VydmljZS5fb3BlbkV4dGVybmFsVXJsKG5leHRTdGVwLnNhbml0aXplZFVybCwgbmV4dFN0ZXAubmV3VGFiKTtcbiAgICAgICAgICAgIGlmIChpc1N1Y2Nlc3NmdWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihgJHtVcmxPcGVuZXJTZXJ2aWNlLkNMQVNTX05BTUV9OiBFeGNlcHRpb24gdGhyb3duIGNhbm5vdCBvcGVuIGV4dGVybmFsIHVybGApKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZXhlY3V0ZUludGVybmFsTmF2aWdhdGlvbih1cmw6IHN0cmluZywgbW9kZWw6IFVybE9wZW5lck1vZGVsLCBuZXh0U3RlcDogTmV4dFN0ZXBNb2RlbCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBjb25zdCB1cmxEYXRhID0gdGhpcy5fZ2V0SW50ZXJuYWxVcmxEYXRhKHVybCk7XG5cbiAgICAgICAgbGV0IGNvbmZpcm1hdGlvblByb21pc2U6IFByb21pc2U8Q29uZmlybWF0aW9uT3V0cHV0TW9kZWw+O1xuXG4gICAgICAgIGlmICh1cmxEYXRhID09PSAnMScgfHwgIW1vZGVsLmV4cGxpY2l0Q29uZmlybWF0aW9uKSB7XG4gICAgICAgICAgICBjb25maXJtYXRpb25Qcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKHsgZG9Ob3RTaG93RnV0dXJlQ29uZmlybWF0aW9uOiBmYWxzZSB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghQ29sbGVjdGlvbnNVdGlsLmlzU3RyaW5nV2l0aENvbnRlbnQobW9kZWwudGl0bGUpKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwudGl0bGUgPSBgUHJvY2VlZCB0byA8Y29kZT4ke3VybH08L2NvZGU+YDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc05pbChtb2RlbC5jb25maXJtQnRuTW9kZWwpKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwuY29uZmlybUJ0bk1vZGVsID0ge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0OiAnUHJvY2VlZCdcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSBlbHNlIGlmICghQ29sbGVjdGlvbnNVdGlsLmlzU3RyaW5nV2l0aENvbnRlbnQobW9kZWwuY29uZmlybUJ0bk1vZGVsLnRleHQpKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwuY29uZmlybUJ0bk1vZGVsLnRleHQgPSAnUHJvY2VlZCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbmZpcm1hdGlvblByb21pc2UgPSB0aGlzLmNvbmZpcm1hdGlvblNlcnZpY2UuY29uZmlybShtb2RlbCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29uZmlybWF0aW9uUHJvbWlzZS50aGVuKChkYXRhKSA9PiB7XG4gICAgICAgICAgICBpZiAoZGF0YS5kb05vdFNob3dGdXR1cmVDb25maXJtYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wZXJzaXN0U2tpcHBlZEludGVybmFsVXJsKHVybCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuZXh0U3RlcC5uZXdUYWIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1N1Y2Nlc3NmdWwgPSBVcmxPcGVuZXJTZXJ2aWNlLl9vcGVuRXh0ZXJuYWxVcmwobmV4dFN0ZXAuc2FuaXRpemVkVXJsLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNTdWNjZXNzZnVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChcbiAgICAgICAgICAgICAgICAgICAgbmV3IEVycm9yKGAke1VybE9wZW5lclNlcnZpY2UuQ0xBU1NfTkFNRX06IEV4Y2VwdGlvbiB0aHJvd24sIGNhbm5vdCBvcGVuIFN1cGVyIENvbGxpZGVyIHVybCBpbiBhIG5ldyB0YWJgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IF9xdWVyeVBhcmFtczogUGFyYW1zID0ge307XG4gICAgICAgICAgICBsZXQgX3Nhbml0aXplZFVybDogc3RyaW5nID0gbmV4dFN0ZXAuc2FuaXRpemVkVXJsO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHF1ZXJ5U3RyaW5nU3RhcnRJbmRleCA9IHVybC5pbmRleE9mKCc/Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocXVlcnlTdHJpbmdTdGFydEluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBfc2FuaXRpemVkVXJsID0gdXJsLnN1YnN0cmluZygwLCBxdWVyeVN0cmluZ1N0YXJ0SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWVyeVN0cmluZyA9IHVybC5zdWJzdHJpbmcocXVlcnlTdHJpbmdTdGFydEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3IFVSTFNlYXJjaFBhcmFtcyhxdWVyeVN0cmluZykuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3F1ZXJ5UGFyYW1zW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGAke1VybE9wZW5lclNlcnZpY2UuQ0xBU1NfTkFNRX06IFBvdGVudGlhbCBidWcgZm91bmQsIEV4Y2VwdGlvbiB0aHJvd24gd2hpbGUgZXh0cmFjdGluZyBxdWVyeSBzdHJpbmcgZm9yIGludGVybmFsIG5hdmlnYXRpb25gXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvblNlcnZpY2UubmF2aWdhdGUoX3Nhbml0aXplZFVybCwgeyBxdWVyeVBhcmFtczogX3F1ZXJ5UGFyYW1zIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRFeHRlcm5hbFVybE9yaWdpbkRhdGEodXJsOiBzdHJpbmcpOiAnMScgfCBudWxsIHtcbiAgICAgICAgY29uc3QgdXJsT3JpZ2luID0gVXJsT3BlbmVyU2VydmljZS5fZ2V0VXJsT3JpZ2luKHVybCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLl9za2lwcGVkT3JpZ2luc1VybHNNYXBbdXJsT3JpZ2luXSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5fc2tpcHBlZE9yaWdpbnNVcmxzTWFwW3VybE9yaWdpbl07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGVyc2lzdFNraXBwZWRFeHRlcm5hbFVybE9yaWdpbih1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmxPcmlnaW4gPSBVcmxPcGVuZXJTZXJ2aWNlLl9nZXRVcmxPcmlnaW4odXJsKTtcblxuICAgICAgICBpZiAoIXVybE9yaWdpbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcGVyc2lzdFNraXBwZWRJbnRlcm5hbFVybCh1cmxPcmlnaW4pO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldEludGVybmFsVXJsRGF0YSh1cmw6IHN0cmluZyk6ICcxJyB8IG51bGwge1xuICAgICAgICBpZiAoIXRoaXMuX3NraXBwZWRPcmlnaW5zVXJsc01hcFt1cmxdKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLl9za2lwcGVkT3JpZ2luc1VybHNNYXBbdXJsXTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9wZXJzaXN0U2tpcHBlZEludGVybmFsVXJsKHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLl9za2lwcGVkT3JpZ2luc1VybHNNYXBbdXJsXSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2tpcHBlZE9yaWdpbnNVcmxzTWFwW3VybF0gPSAnMSc7XG5cbiAgICAgICAgdGhpcy5fcGVyc2lzdFNraXBwZWRVcmxzTWFwKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZXh0cmFjdFNraXBwZWRVcmxzTWFwKCk6IFJlY29yZDxzdHJpbmcsICcxJz4ge1xuICAgICAgICBjb25zdCBleHRyYWN0ZWRPcmlnaW5zTWFwID0gdGhpcy5jb29raWVTZXJ2aWNlLmdldCh0aGlzLl9jb29raWVLZXkpO1xuICAgICAgICBpZiAoIWV4dHJhY3RlZE9yaWdpbnNNYXApIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGVjb2RlZE9yaWdpbnNNYXAgPSBVcmxPcGVuZXJTZXJ2aWNlLl9kZWNvZGVCYXNlNjQoZXh0cmFjdGVkT3JpZ2luc01hcCk7XG4gICAgICAgIGlmICghZGVjb2RlZE9yaWdpbnNNYXApIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFyc2VkT3JpZ2luc01hcCA9IFVybE9wZW5lclNlcnZpY2UuX3BhcnNlVG9KU09OPFJlY29yZDxzdHJpbmcsICcxJz4+KGRlY29kZWRPcmlnaW5zTWFwKTtcbiAgICAgICAgaWYgKCFwYXJzZWRPcmlnaW5zTWFwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXJzZWRPcmlnaW5zTWFwO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3BlcnNpc3RTa2lwcGVkVXJsc01hcCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLl9za2lwcGVkT3JpZ2luc1VybHNNYXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNlcmlhbGl6ZWRPcmlnaW5zTWFwID0gVXJsT3BlbmVyU2VydmljZS5fc2VyaWFsaXplT2JqZWN0KHRoaXMuX3NraXBwZWRPcmlnaW5zVXJsc01hcCk7XG4gICAgICAgIGlmICghc2VyaWFsaXplZE9yaWdpbnNNYXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVuY29kZWRPcmlnaW5zTWFwID0gVXJsT3BlbmVyU2VydmljZS5fZW5jb2RlQmFzZTY0KHNlcmlhbGl6ZWRPcmlnaW5zTWFwKTtcbiAgICAgICAgaWYgKCFlbmNvZGVkT3JpZ2luc01hcCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb29raWVTZXJ2aWNlLnNldCh0aGlzLl9jb29raWVLZXksIGVuY29kZWRPcmlnaW5zTWFwKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfb3BlbkV4dGVybmFsVXJsKHVybDogc3RyaW5nLCBuZXdUYWI6IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdpbmRvdy5vcGVuKHVybCwgbmV3VGFiID8gJ19ibGFuaycgOiAnX3NlbGYnLCAnbm9vcGVuZXInKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICAgICAgYCR7VXJsT3BlbmVyU2VydmljZS5DTEFTU19OQU1FfTogQ2Fubm90IG9wZW4gZXh0ZXJuYWwgdXJsLCBjaGVjayB5b3VyIEJyb3dzZXIgc2VjdXJpdHkgY29uZmlnIGlmIGFsbG93cyBvcGVuaW5nIG5ldyB0YWJzYFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX2dldFVybE9yaWdpbih1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBfdXJsID0gbmV3IFVSTCh1cmwpO1xuXG4gICAgICAgICAgICByZXR1cm4gX3VybC5vcmlnaW47XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7VXJsT3BlbmVyU2VydmljZS5DTEFTU19OQU1FfTogUG90ZW50aWFsIGJ1ZyBmb3VuZCwgY2Fubm90IGV4dHJhY3Qgb3JpZ2luIGZyb20gdXJsYCk7XG5cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX2VuY29kZUJhc2U2NCh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGJ0b2EodmFsdWUpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGAke1VybE9wZW5lclNlcnZpY2UuQ0xBU1NfTkFNRX06IFBvdGVudGlhbCBidWcgZm91bmQsIHByb3ZpZGVkIHZhbHVlIGNhbm5vdCBiZSBlbmNvZGVkIHRvIGJhc2U2NGApO1xuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9kZWNvZGVCYXNlNjQodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBhdG9iKHZhbHVlKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgJHtVcmxPcGVuZXJTZXJ2aWNlLkNMQVNTX05BTUV9OiBQb3RlbnRpYWwgYnVnIGZvdW5kLCBwcm92aWRlZCB2YWx1ZSBjYW5ub3QgYmUgZGVjb2RlZCBmcm9tIGJhc2U2NGApO1xuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9zZXJpYWxpemVPYmplY3QodmFsdWU6IHVua25vd24pOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGAke1VybE9wZW5lclNlcnZpY2UuQ0xBU1NfTkFNRX06IFBvdGVudGlhbCBidWcgZm91bmQsIGNhbm5vdCBzZXJpYWxpemUgcHJvdmlkZWQgb2JqZWN0YCk7XG5cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX3BhcnNlVG9KU09OPFQ+KHZhbHVlOiBzdHJpbmcpOiBUIHtcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodmFsdWUpIGFzIFQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7VXJsT3BlbmVyU2VydmljZS5DTEFTU19OQU1FfTogUG90ZW50aWFsIGJ1ZyBmb3VuZCwgY2Fubm90IHBhcnNlIHByb3ZpZGVkIEpTT05gKTtcblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=