@hpe/angular-toolkit
Version:
Hewlett-Packard Enterprise : Angular toolkit for rapid project development
680 lines (668 loc) • 70.7 kB
JavaScript
import { EventEmitter, Injectable, NgModule } from '@angular/core';
import { AppEvent } from '@hpe/angular-toolkit/model';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';
import { throwError } from 'rxjs';
import { catchError, map, finalize } from 'rxjs/operators';
import { MessageService } from 'primeng/components/common/messageservice';
import { CommonModule } from '@angular/common';
import { MessageService as MessageService$1 } from 'primeng/api';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
//=============================================================================
//===
//=== (C) Copyright 2018 Hewlett Packard Enterprise Development LP.
//===
//=== Use of this source code is governed by an MIT-style license that can be
//=== found in the LICENSE file
//=============================================================================
class AbstractSubscriber {
/**
* @param {?} eventBusService
*/
constructor(eventBusService) {
this.eventBusService = eventBusService;
this.subscriptions = [];
}
/**
* @return {?}
*/
ngOnDestroy() {
this.subscriptions.forEach((s) => s.unsubscribe());
}
/**
* @param {?} eventCode
* @param {?} handler
* @return {?}
*/
subscribeToApp(eventCode, handler) {
let /** @type {?} */ s = this.eventBusService.subscribeToApp(eventCode, handler);
this.subscriptions.push(s);
return s;
}
/**
* @param {?} event
* @return {?}
*/
emitToApp(event) {
this.eventBusService.emitToApp(event);
}
/**
* @param {?} handler
* @return {?}
*/
subscribeToError(handler) {
let /** @type {?} */ s = this.eventBusService.subscribeToError(handler);
this.subscriptions.push(s);
return s;
}
/**
* @param {?} event
* @return {?}
*/
emitToError(event) {
this.eventBusService.emitToError(event);
}
}
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class EventBusService {
constructor() {
this.eventEmitterMap = new Map();
this.errorEvents = new EventEmitter();
}
/**
* @param {?} eventCode
* @param {?} handler
* @return {?}
*/
subscribeToApp(eventCode, handler) {
let /** @type {?} */ emitter = this.eventEmitterMap.get(eventCode);
if (emitter == null) {
emitter = new EventEmitter();
this.eventEmitterMap.set(eventCode, emitter);
}
return emitter.subscribe(handler, null, null);
}
/**
* @param {?} event
* @return {?}
*/
emitToApp(event) {
let /** @type {?} */ emitter = this.eventEmitterMap.get(event.code);
if (emitter != null) {
console.log("Emitting event : " + JSON.stringify(event));
emitter.emit(event);
}
else {
console.log("WARNING : Emitting an event without any handler : " + JSON.stringify(event));
}
//--- Emitting to global handlers
emitter = this.eventEmitterMap.get(AppEvent.ANY);
if (emitter != null) {
emitter.emit(event);
}
}
/**
* @param {?} handler
* @return {?}
*/
subscribeToError(handler) {
return this.errorEvents.subscribe(handler, null, null);
}
/**
* @param {?} event
* @return {?}
*/
emitToError(event) {
console.log("Emitting error event : " + JSON.stringify(event));
this.errorEvents.emit(event);
}
}
EventBusService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
EventBusService.ctorParameters = () => [];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/** @enum {number} */
const Status = {
LOGIN: 0,
LOADING: 1,
READY: 2,
};
Status[Status.LOGIN] = "LOGIN";
Status[Status.LOADING] = "LOADING";
Status[Status.READY] = "READY";
class ApplicationService extends AbstractSubscriber {
/**
* @param {?} eventBusService
*/
constructor(eventBusService) {
super(eventBusService);
this.status = Status.LOGIN;
super.subscribeToApp(AppEvent.LOGIN_SUCCESS, (event) => this.onLoginSuccess(event));
super.subscribeToApp(AppEvent.LOGIN_FAILED, (event) => this.onLoginFailed(event));
super.subscribeToApp(AppEvent.LOGOUT_SUCCESS, (event) => this.onLogoutSuccess(event));
super.subscribeToApp(AppEvent.LOGOUT_FAILED, (event) => this.onLogoutFailed(event));
super.subscribeToApp(AppEvent.INVALID_TOKEN, (event) => this.onInvalidToken(event));
super.subscribeToApp(AppEvent.APPLICATION_READY, (event) => this.onApplicationReady(event));
}
/**
* @return {?}
*/
isStatusLogin() {
return this.status == Status.LOGIN;
}
/**
* @return {?}
*/
isStatusLoading() {
return this.status == Status.LOADING;
}
/**
* @return {?}
*/
isStatusReady() {
return this.status == Status.READY;
}
/**
* @param {?} event
* @return {?}
*/
onLoginSuccess(event) {
this.status = Status.LOADING;
}
/**
* @param {?} event
* @return {?}
*/
onLoginFailed(event) {
this.status = Status.LOGIN;
}
/**
* @param {?} event
* @return {?}
*/
onLogoutSuccess(event) {
this.status = Status.LOGIN;
}
/**
* @param {?} event
* @return {?}
*/
onLogoutFailed(event) {
this.status = Status.LOGIN;
}
/**
* @param {?} event
* @return {?}
*/
onInvalidToken(event) {
this.status = Status.LOGIN;
}
/**
* @param {?} event
* @return {?}
*/
onApplicationReady(event) {
this.status = Status.READY;
}
}
ApplicationService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ApplicationService.ctorParameters = () => [
{ type: EventBusService, },
];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class HttpService {
/**
* @param {?} httpClient
* @param {?} eventBusService
* @param {?} domSanitizer
*/
constructor(httpClient, eventBusService, domSanitizer) {
this.httpClient = httpClient;
this.eventBusService = eventBusService;
this.domSanitizer = domSanitizer;
this.openRequests = 0;
}
/**
* @return {?}
*/
get loading() {
return (this.openRequests > 0);
}
/**
* @param {?} url
* @param {?=} options
* @return {?}
*/
getObject(url, options) {
this.showLoader();
//--- "Pragma": "no-cache" for IE 11
let /** @type {?} */ header = {
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"Expires": "0"
};
return this.httpClient.get(url, { params: options, headers: header }).pipe(catchError((error) => this.handleError(error)), finalize(() => this.hideLoader()));
}
/**
* @param {?} url
* @param {?=} options
* @return {?}
*/
getBlob(url, options) {
this.showLoader();
//--- Add timestamp to change static url to dynamic for IE 11
if (options != null) {
options.ts = Date.now();
}
return this.httpClient.get(url, { params: options, responseType: 'blob' }).pipe(map(e => this.getSanitizedUrl(URL.createObjectURL(e))), catchError((error) => this.handleError(error)), finalize(() => this.hideLoader()));
}
/**
* @param {?} url
* @param {?} object
* @param {?=} options
* @return {?}
*/
postObject(url, object, options) {
this.showLoader();
return this.httpClient.post(url, object, options).pipe(catchError((error) => this.handleError(error)), finalize(() => this.hideLoader()));
}
/**
* @param {?} url
* @return {?}
*/
getSanitizedUrl(url) {
return this.domSanitizer.bypassSecurityTrustResourceUrl(url);
}
/**
* @param {?} response
* @return {?}
*/
handleError(response) {
console.log("Got the following HTTP error : " + JSON.stringify(response));
let /** @type {?} */ error;
if (response.status == 422) {
//--- Unprocessable entity
error = response.error;
}
else {
error = {
code: response.status.toString(),
error: response.error.toString()
};
}
this.eventBusService.emitToError(error);
return throwError(error);
}
/**
* @return {?}
*/
showLoader() {
if (++this.openRequests == 1) {
this.eventBusService.emitToApp(new AppEvent(AppEvent.SUBMIT_START));
}
}
/**
* @return {?}
*/
hideLoader() {
if (--this.openRequests == 0) {
this.eventBusService.emitToApp(new AppEvent(AppEvent.SUBMIT_END));
}
}
}
HttpService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
HttpService.ctorParameters = () => [
{ type: HttpClient, },
{ type: EventBusService, },
{ type: DomSanitizer, },
];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class LabelService {
/**
* @param {?} httpService
*/
constructor(httpService) {
this.httpService = httpService;
this.languages = ["en", "it"];
this.labelSet = new Map();
this.language = "en";
//--- Load language files
this.languages.forEach((language) => {
this.initLanguage(language);
});
}
/**
* @param {?} language
* @return {?}
*/
setLanguage(language) {
this.language = language;
}
/**
* @param {?} entity
* @param {?} code
* @return {?}
*/
getLabel(entity, code) {
if (code == null) {
return null;
}
let /** @type {?} */ entitySet = this.getMapping(entity);
if (entitySet == null) {
return "?" + entity + "?";
}
let /** @type {?} */ label = entitySet[code];
if (label == null) {
return entity + ".?" + code + "?";
}
return label;
}
/**
* @param {?} entity
* @return {?}
*/
getMapping(entity) {
let /** @type {?} */ labels = this.labelSet.get(this.language);
if (labels != null) {
return labels.get(entity);
}
//--- Probably, we are still loading data
return null;
}
/**
* @param {?} language
* @return {?}
*/
initLanguage(language) {
this.loadLanguageFile(language, LabelService.TOOLKIT_FILE);
this.loadLanguageFile(language, LabelService.APPLICATION_FILE);
}
/**
* @param {?} language
* @param {?} name
* @return {?}
*/
loadLanguageFile(language, name) {
let /** @type {?} */ file = name + "-" + language + ".json";
this.httpService.getObject("asset/lang/" + file)
.subscribe(result => this.processFile(language, file, result), error => console.log("Cannot load labels file : " + file));
}
/**
* @param {?} language
* @param {?} file
* @param {?} data
* @return {?}
*/
processFile(language, file, data) {
console.log("Loaded labels file : " + file);
let /** @type {?} */ labels = this.labelSet.get(language);
if (labels == null) {
labels = new Map();
this.labelSet.set(language, labels);
}
for (let /** @type {?} */ key in data) {
labels.set(key, data[key]);
}
}
}
LabelService.TOOLKIT_FILE = "toolkit";
LabelService.APPLICATION_FILE = "application";
LabelService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
LabelService.ctorParameters = () => [
{ type: HttpService, },
];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class NotificationService {
/**
* @param {?} messageService
*/
constructor(messageService) {
this.messageService = messageService;
}
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
showSuccess(title, message) {
this.show('success', title, message);
}
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
showInfo(title, message) {
this.show('info', title, message);
}
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
showWarn(title, message) {
this.show('warn', title, message);
}
/**
* @param {?} title
* @param {?} message
* @return {?}
*/
showError(title, message) {
this.show('error', title, message);
}
/**
* @param {?} severity
* @param {?} title
* @param {?} message
* @return {?}
*/
show(severity, title, message) {
this.messageService.add({
severity: severity,
summary: title,
detail: message
});
}
}
NotificationService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
NotificationService.ctorParameters = () => [
{ type: MessageService, },
];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class SessionService extends AbstractSubscriber {
/**
* @param {?} eventBusService
* @param {?} httpService
*/
constructor(eventBusService, httpService) {
super(eventBusService);
this.httpService = httpService;
this.clearSession();
super.subscribeToApp(AppEvent.INVALID_TOKEN, event => this.onInvalidToken(event));
}
/**
* @param {?} cred
* @return {?}
*/
login(cred) {
console.log("SessionService.login : Logging in user='" + cred.username + "'");
//--- Loads user profile from server
this.httpService.postObject("/api/session/login", cred)
.subscribe(result => this.loginSuccess(result), error => this.loginError(error));
}
/**
* @return {?}
*/
logout() {
console.log("SessionService.logout : Logging out user='" + (this.user || "???") + "'");
this.httpService.postObject("/api/session/logout", { token: this.token })
.subscribe(result => this.logoutSuccess(), error => this.logoutError(error));
}
/**
* @return {?}
*/
clearSession() {
console.log("SessionService.clearSession: Resetting session...");
this.session = null;
this.token = null;
this.user = null;
this.profile = null;
this.permissions = new Map();
}
/**
* @return {?}
*/
get homePage() {
return (this.profile)
? this.profile.homePage
: null;
}
/**
* @param {?} name
* @return {?}
*/
hasPermission(name) {
return (this.permissions.get(name));
}
/**
* @param {?} session
* @return {?}
*/
loginSuccess(session) {
this.session = session;
this.token = session.token;
this.user = session.user;
this.profile = session.profile;
this.permissions = this.setupPermissionMap(this.profile.permissions);
super.emitToApp(new AppEvent(AppEvent.LOGIN_SUCCESS, session));
console.log("Login successful for user=" + this.user.username);
}
/**
* @param {?} response
* @return {?}
*/
loginError(response) {
super.emitToApp(new AppEvent(AppEvent.LOGIN_FAILED, response));
}
/**
* @return {?}
*/
logoutSuccess() {
let /** @type {?} */ username = this.user.username;
this.clearSession();
super.emitToApp(new AppEvent(AppEvent.LOGOUT_SUCCESS, username));
console.log("Logout successful for user=" + username);
}
/**
* @param {?} response
* @return {?}
*/
logoutError(response) {
this.clearSession();
super.emitToApp(new AppEvent(AppEvent.LOGOUT_FAILED));
}
/**
* @param {?} permissions
* @return {?}
*/
setupPermissionMap(permissions) {
let /** @type {?} */ map$$1 = new Map();
permissions.forEach((p) => map$$1.set(p, true));
return map$$1;
}
/**
* @param {?} event
* @return {?}
*/
onInvalidToken(event) {
this.clearSession();
}
}
SessionService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
SessionService.ctorParameters = () => [
{ type: EventBusService, },
{ type: HttpService, },
];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
//=============================================================================
class HpeServiceModule {
}
HpeServiceModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule
],
declarations: [],
exports: [],
providers: [
ApplicationService,
EventBusService,
HttpService,
LabelService,
NotificationService,
SessionService,
MessageService$1
],
},] },
];
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
//=============================================================================
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
export { HpeServiceModule, AbstractSubscriber, ApplicationService, EventBusService, HttpService, LabelService, NotificationService, SessionService };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHBlLWFuZ3VsYXItdG9vbGtpdC1zZXJ2aWNlLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL2Fic3RyYWN0LXN1YnNjcmliZXIudHMiLCJuZzovL0BocGUvYW5ndWxhci10b29sa2l0L3NlcnZpY2UvZXZlbnRidXMtc2VydmljZS50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvc2VydmljZS9hcHBsaWNhdGlvbi1zZXJ2aWNlLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL2h0dHAtc2VydmljZS50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvc2VydmljZS9sYWJlbC1zZXJ2aWNlLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL25vdGlmaWNhdGlvbi1zZXJ2aWNlLnRzIiwibmc6Ly9AaHBlL2FuZ3VsYXItdG9vbGtpdC9zZXJ2aWNlL3Nlc3Npb24tc2VydmljZS50cyIsIm5nOi8vQGhwZS9hbmd1bGFyLXRvb2xraXQvc2VydmljZS9tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy89PT1cbi8vPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbi8vPT09XG4vLz09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuLy89PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5pbXBvcnQge09uRGVzdHJveX0gICAgZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tIFwicnhqc1wiO1xuXG5pbXBvcnQge0V2ZW50SGFuZGxlciwgRXJyb3JIYW5kbGVyLCBBcHBFdmVudCwgRXJyb3JFdmVudH0gZnJvbSBcIkBocGUvYW5ndWxhci10b29sa2l0L21vZGVsXCI7XG5cbmltcG9ydCB7RXZlbnRCdXNTZXJ2aWNlfSBmcm9tIFwiLi9ldmVudGJ1cy1zZXJ2aWNlXCI7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGNsYXNzIEFic3RyYWN0U3Vic2NyaWJlciBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFZhcmlhYmxlc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIENvbnN0cnVjdG9yXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGNvbnN0cnVjdG9yKHByaXZhdGUgZXZlbnRCdXNTZXJ2aWNlIDogRXZlbnRCdXNTZXJ2aWNlKSB7fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBMaWZlY3ljbGUgbWV0aG9kc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgbmdPbkRlc3Ryb3koKSB7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goIChzIDogU3Vic2NyaXB0aW9uKSA9PiBzLnVuc3Vic2NyaWJlKCkpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIEFQSSBtZXRob2RzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByb3RlY3RlZCBzdWJzY3JpYmVUb0FwcChldmVudENvZGUgOiBzdHJpbmcsIGhhbmRsZXIgOiBFdmVudEhhbmRsZXIpIDogU3Vic2NyaXB0aW9uIHtcblxuXHRcdGxldCBzIDogU3Vic2NyaXB0aW9uID0gdGhpcy5ldmVudEJ1c1NlcnZpY2Uuc3Vic2NyaWJlVG9BcHAoZXZlbnRDb2RlLCBoYW5kbGVyKTtcblx0XHR0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChzKTtcblxuXHRcdHJldHVybiBzO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJvdGVjdGVkIGVtaXRUb0FwcChldmVudCA6IEFwcEV2ZW50KSA6IHZvaWQge1xuXHRcdHRoaXMuZXZlbnRCdXNTZXJ2aWNlLmVtaXRUb0FwcChldmVudCk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcm90ZWN0ZWQgc3Vic2NyaWJlVG9FcnJvcihoYW5kbGVyIDogRXJyb3JIYW5kbGVyKSA6IFN1YnNjcmlwdGlvbiB7XG5cblx0XHRsZXQgcyA6IFN1YnNjcmlwdGlvbiA9IHRoaXMuZXZlbnRCdXNTZXJ2aWNlLnN1YnNjcmliZVRvRXJyb3IoaGFuZGxlcik7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb25zLnB1c2gocyk7XG5cblx0XHRyZXR1cm4gcztcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByb3RlY3RlZCBlbWl0VG9FcnJvcihldmVudCA6IEVycm9yRXZlbnQpIDogdm9pZCB7XG5cdFx0dGhpcy5ldmVudEJ1c1NlcnZpY2UuZW1pdFRvRXJyb3IoZXZlbnQpO1xuXHR9XG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtFdmVudEVtaXR0ZXIsIEluamVjdGFibGV9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5cbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tIFwicnhqc1wiO1xuXG5pbXBvcnQge0FwcEV2ZW50LCBFcnJvckV2ZW50LCBFcnJvckhhbmRsZXIsIEV2ZW50SGFuZGxlcn0gZnJvbSBcIkBocGUvYW5ndWxhci10b29sa2l0L21vZGVsXCI7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEV2ZW50QnVzU2VydmljZSB7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFZhcmlhYmxlc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIGV2ZW50RW1pdHRlck1hcCA6IE1hcDxzdHJpbmcsIEV2ZW50RW1pdHRlcjxBcHBFdmVudD4+ID0gbmV3IE1hcCgpO1xuXHRwcml2YXRlIGVycm9yRXZlbnRzICAgICA6IEV2ZW50RW1pdHRlcjxFcnJvckV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQ29uc3RydWN0b3Jcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHN1YnNjcmliZVRvQXBwKGV2ZW50Q29kZSA6IHN0cmluZywgaGFuZGxlciA6IEV2ZW50SGFuZGxlcikgOiBTdWJzY3JpcHRpb24ge1xuXG5cdFx0bGV0IGVtaXR0ZXIgOiBFdmVudEVtaXR0ZXI8QXBwRXZlbnQ+ID0gdGhpcy5ldmVudEVtaXR0ZXJNYXAuZ2V0KGV2ZW50Q29kZSk7XG5cblx0XHRpZiAoZW1pdHRlciA9PSBudWxsKSB7XG5cdFx0XHRlbWl0dGVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXHRcdFx0dGhpcy5ldmVudEVtaXR0ZXJNYXAuc2V0KGV2ZW50Q29kZSwgZW1pdHRlcik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGVtaXR0ZXIuc3Vic2NyaWJlKGhhbmRsZXIsIG51bGwsIG51bGwpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIGVtaXRUb0FwcChldmVudCA6IEFwcEV2ZW50KSA6IHZvaWQge1xuXG5cdFx0bGV0IGVtaXR0ZXIgPSB0aGlzLmV2ZW50RW1pdHRlck1hcC5nZXQoZXZlbnQuY29kZSk7XG5cblx0XHRpZiAoZW1pdHRlciAhPSBudWxsKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIkVtaXR0aW5nIGV2ZW50IDogXCIrIEpTT04uc3RyaW5naWZ5KGV2ZW50KSk7XG5cdFx0XHRlbWl0dGVyLmVtaXQoZXZlbnQpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGNvbnNvbGUubG9nKFwiV0FSTklORyA6IEVtaXR0aW5nIGFuIGV2ZW50IHdpdGhvdXQgYW55IGhhbmRsZXIgOiBcIisgSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTtcblx0XHR9XG5cblx0XHQvLy0tLSBFbWl0dGluZyB0byBnbG9iYWwgaGFuZGxlcnNcblxuXHRcdGVtaXR0ZXIgPSB0aGlzLmV2ZW50RW1pdHRlck1hcC5nZXQoQXBwRXZlbnQuQU5ZKTtcblxuXHRcdGlmIChlbWl0dGVyICE9IG51bGwpIHtcblx0XHRcdGVtaXR0ZXIuZW1pdChldmVudCk7XG5cdFx0fVxuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHN1YnNjcmliZVRvRXJyb3IoaGFuZGxlciA6IEVycm9ySGFuZGxlcikgOiBTdWJzY3JpcHRpb24ge1xuXHRcdHJldHVybiB0aGlzLmVycm9yRXZlbnRzLnN1YnNjcmliZShoYW5kbGVyLCBudWxsLCBudWxsKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBlbWl0VG9FcnJvcihldmVudCA6IEVycm9yRXZlbnQpIDogdm9pZCB7XG5cdFx0Y29uc29sZS5sb2coXCJFbWl0dGluZyBlcnJvciBldmVudCA6IFwiKyBKU09OLnN0cmluZ2lmeShldmVudCkpO1xuXHRcdHRoaXMuZXJyb3JFdmVudHMuZW1pdChldmVudCk7XG5cdH1cbn1cblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIiwiLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy89PT1cbi8vPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbi8vPT09XG4vLz09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuLy89PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5pbXBvcnQge0luamVjdGFibGV9ICAgICAgICAgZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0FwcEV2ZW50fSAgICAgICAgICAgZnJvbSBcIkBocGUvYW5ndWxhci10b29sa2l0L21vZGVsXCI7XG5cbmltcG9ydCB7QWJzdHJhY3RTdWJzY3JpYmVyfSBmcm9tIFwiLi9hYnN0cmFjdC1zdWJzY3JpYmVyXCI7XG5pbXBvcnQge0V2ZW50QnVzU2VydmljZX0gICAgZnJvbSBcIi4vZXZlbnRidXMtc2VydmljZVwiO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmVudW0gU3RhdHVzIHtcblx0TE9HSU4sXG5cdExPQURJTkcsXG5cdFJFQURZXG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uU2VydmljZSBleHRlbmRzIEFic3RyYWN0U3Vic2NyaWJlciB7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFZhcmlhYmxlc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIHN0YXR1cyA6IFN0YXR1cyA9IFN0YXR1cy5MT0dJTjtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQ29uc3RydWN0b3Jcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Y29uc3RydWN0b3IoZXZlbnRCdXNTZXJ2aWNlOiBFdmVudEJ1c1NlcnZpY2UpIHtcblxuXHRcdHN1cGVyKGV2ZW50QnVzU2VydmljZSk7XG5cblx0XHRzdXBlci5zdWJzY3JpYmVUb0FwcChBcHBFdmVudC5MT0dJTl9TVUNDRVNTLCAgICAgKGV2ZW50IDogQXBwRXZlbnQpID0+IHRoaXMub25Mb2dpblN1Y2Nlc3MgICAgKGV2ZW50KSk7XG5cdFx0c3VwZXIuc3Vic2NyaWJlVG9BcHAoQXBwRXZlbnQuTE9HSU5fRkFJTEVELCAgICAgIChldmVudCA6IEFwcEV2ZW50KSA9PiB0aGlzLm9uTG9naW5GYWlsZWQgICAgIChldmVudCkpO1xuXHRcdHN1cGVyLnN1YnNjcmliZVRvQXBwKEFwcEV2ZW50LkxPR09VVF9TVUNDRVNTLCAgICAoZXZlbnQgOiBBcHBFdmVudCkgPT4gdGhpcy5vbkxvZ291dFN1Y2Nlc3MgICAoZXZlbnQpKTtcblx0XHRzdXBlci5zdWJzY3JpYmVUb0FwcChBcHBFdmVudC5MT0dPVVRfRkFJTEVELCAgICAgKGV2ZW50IDogQXBwRXZlbnQpID0+IHRoaXMub25Mb2dvdXRGYWlsZWQgICAgKGV2ZW50KSk7XG5cdFx0c3VwZXIuc3Vic2NyaWJlVG9BcHAoQXBwRXZlbnQuSU5WQUxJRF9UT0tFTiwgICAgIChldmVudCA6IEFwcEV2ZW50KSA9PiB0aGlzLm9uSW52YWxpZFRva2VuICAgIChldmVudCkpO1xuXHRcdHN1cGVyLnN1YnNjcmliZVRvQXBwKEFwcEV2ZW50LkFQUExJQ0FUSU9OX1JFQURZLCAoZXZlbnQgOiBBcHBFdmVudCkgPT4gdGhpcy5vbkFwcGxpY2F0aW9uUmVhZHkoZXZlbnQpKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBBUEkgbWV0aG9kc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgaXNTdGF0dXNMb2dpbigpIDogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuc3RhdHVzID09IFN0YXR1cy5MT0dJTjtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBpc1N0YXR1c0xvYWRpbmcoKSA6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLnN0YXR1cyA9PSBTdGF0dXMuTE9BRElORztcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBpc1N0YXR1c1JlYWR5KCkgOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5zdGF0dXMgPT0gU3RhdHVzLlJFQURZO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIEV2ZW50c1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIG9uTG9naW5TdWNjZXNzKGV2ZW50IDogQXBwRXZlbnQpIHtcblx0XHR0aGlzLnN0YXR1cyA9IFN0YXR1cy5MT0FESU5HO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBvbkxvZ2luRmFpbGVkKGV2ZW50IDogQXBwRXZlbnQpIHtcblx0XHR0aGlzLnN0YXR1cyA9IFN0YXR1cy5MT0dJTjtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgb25Mb2dvdXRTdWNjZXNzKGV2ZW50IDogQXBwRXZlbnQpIHtcblx0XHR0aGlzLnN0YXR1cyA9IFN0YXR1cy5MT0dJTjtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgb25Mb2dvdXRGYWlsZWQoZXZlbnQgOiBBcHBFdmVudCkge1xuXHRcdHRoaXMuc3RhdHVzID0gU3RhdHVzLkxPR0lOO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBvbkludmFsaWRUb2tlbihldmVudCA6IEFwcEV2ZW50KSB7XG5cdFx0dGhpcy5zdGF0dXMgPSBTdGF0dXMuTE9HSU47XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIG9uQXBwbGljYXRpb25SZWFkeShldmVudCA6IEFwcEV2ZW50KSB7XG5cdFx0dGhpcy5zdGF0dXMgPSBTdGF0dXMuUkVBRFk7XG5cdH1cbn1cblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIiwiLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy89PT1cbi8vPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbi8vPT09XG4vLz09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuLy89PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5pbXBvcnQge0luamVjdGFibGV9ICAgZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7SHR0cENsaWVudH0gICBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcbmltcG9ydCB7RG9tU2FuaXRpemVyfSBmcm9tIFwiQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3NlclwiO1xuaW1wb3J0IHtTYWZlVXJsfSAgICAgIGZyb20gXCJAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyL3NyYy9zZWN1cml0eS9kb21fc2FuaXRpemF0aW9uX3NlcnZpY2VcIjtcblxuaW1wb3J0IHtPYnNlcnZhYmxlLCB0aHJvd0Vycm9yfSAgICBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHtjYXRjaEVycm9yLCBtYXAsIGZpbmFsaXplfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcbmltcG9ydCB7QXBwRXZlbnQsIEVycm9yRXZlbnQgfSAgICAgZnJvbSBcIkBocGUvYW5ndWxhci10b29sa2l0L21vZGVsXCI7XG5cbmltcG9ydCB7RXZlbnRCdXNTZXJ2aWNlfSAgICAgICAgICAgZnJvbSBcIi4vZXZlbnRidXMtc2VydmljZVwiXG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEh0dHBTZXJ2aWNlIHtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gVmFyaWFibGVzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgb3BlblJlcXVlc3RzIDogbnVtYmVyID0gMDtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQ29uc3RydWN0b3Jcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Y29uc3RydWN0b3IocHJpdmF0ZSBodHRwQ2xpZW50ICAgICAgOiBIdHRwQ2xpZW50LFxuXHRcdFx0XHRwcml2YXRlIGV2ZW50QnVzU2VydmljZSA6IEV2ZW50QnVzU2VydmljZSxcblx0XHRcdFx0cHJpdmF0ZSBkb21TYW5pdGl6ZXIgICAgOiBEb21TYW5pdGl6ZXIgKSB7fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBBUEkgbWV0aG9kc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgZ2V0IGxvYWRpbmcoKSA6IGJvb2xlYW4ge1xuXHRcdHJldHVybiAodGhpcy5vcGVuUmVxdWVzdHMgPiAwKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBnZXRPYmplY3QodXJsIDogc3RyaW5nLCBvcHRpb25zPyA6IGFueSk6IE9ic2VydmFibGU8YW55PiB7XG5cblx0XHR0aGlzLnNob3dMb2FkZXIoKTtcblxuXHRcdC8vLS0tIFwiUHJhZ21hXCI6IFwibm8tY2FjaGVcIiBmb3IgSUUgMTFcblxuXHRcdGxldCBoZWFkZXIgPSB7XG5cdFx0XHRcIlByYWdtYVwiICAgICAgICA6IFwibm8tY2FjaGVcIixcblx0XHRcdFwiQ2FjaGUtQ29udHJvbFwiIDogXCJuby1jYWNoZVwiLFxuXHRcdFx0XCJFeHBpcmVzXCIgICAgICAgOiBcIjBcIlxuXHRcdH07XG5cblx0XHRyZXR1cm4gdGhpcy5odHRwQ2xpZW50LmdldCh1cmwsIHsgcGFyYW1zOiBvcHRpb25zLCBoZWFkZXJzIDogaGVhZGVyIH0pLnBpcGUoXG5cdFx0XHRjYXRjaEVycm9yKChlcnJvcikgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnJvcikpLFxuXHRcdFx0ZmluYWxpemUgICgoKSAgICAgID0+IHRoaXMuaGlkZUxvYWRlcigpKVxuXHRcdCk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgZ2V0QmxvYih1cmwgOiBzdHJpbmcsIG9wdGlvbnM/IDogYW55KTogT2JzZXJ2YWJsZTxhbnk+IHtcblxuXHRcdHRoaXMuc2hvd0xvYWRlcigpO1xuXG5cdFx0Ly8tLS0gQWRkIHRpbWVzdGFtcCB0byBjaGFuZ2Ugc3RhdGljIHVybCB0byBkeW5hbWljIGZvciBJRSAxMVxuXG5cdFx0aWYgKG9wdGlvbnMgIT0gbnVsbCkge1xuXHRcdFx0b3B0aW9ucy50cyA9IERhdGUubm93KCk7XG5cdFx0fVxuXG4gICAgICAgIHJldHVybiB0aGlzLmh0dHBDbGllbnQuZ2V0KHVybCwgeyBwYXJhbXM6IG9wdGlvbnMsIHJlc3BvbnNlVHlwZSA6ICdibG9iJ30pLnBpcGUoXG5cdFx0XHRtYXAoZSA9PiB0aGlzLmdldFNhbml0aXplZFVybChVUkwuY3JlYXRlT2JqZWN0VVJMKGUpKSksXG5cdFx0XHRjYXRjaEVycm9yKChlcnJvcikgPT4gdGhpcy5oYW5kbGVFcnJvcihlcnJvcikpLFxuXHRcdFx0ZmluYWxpemUoKCkgPT4gdGhpcy5oaWRlTG9hZGVyKCkpXG5cdFx0KTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBwb3N0T2JqZWN0KHVybDogc3RyaW5nLCBvYmplY3Q6IGFueSwgb3B0aW9ucz86IGFueSk6IE9ic2VydmFibGU8YW55PiB7XG5cbiAgICAgICAgdGhpcy5zaG93TG9hZGVyKCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5wb3N0ICh1cmwsIG9iamVjdCwgb3B0aW9ucykucGlwZShcblx0XHRcdGNhdGNoRXJyb3IoKGVycm9yKSA9PiB0aGlzLmhhbmRsZUVycm9yKGVycm9yKSksXG5cdFx0XHRmaW5hbGl6ZSAgKCgpICAgICAgPT4gdGhpcy5oaWRlTG9hZGVyKCkpXG5cdFx0KTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBnZXRTYW5pdGl6ZWRVcmwodXJsIDogc3RyaW5nKTogU2FmZVVybCB7XG5cdFx0cmV0dXJuIHRoaXMuZG9tU2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybCh1cmwpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFByaXZhdGUgbWV0aG9kc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIGhhbmRsZUVycm9yKHJlc3BvbnNlIDogYW55KSA6IE9ic2VydmFibGU8YW55PiB7XG5cblx0XHRjb25zb2xlLmxvZyhcIkdvdCB0aGUgZm9sbG93aW5nIEhUVFAgZXJyb3IgOiBcIiArIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSk7XG5cblx0XHRsZXQgZXJyb3IgOiBFcnJvckV2ZW50O1xuXG5cdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyA9PSA0MjIpIHtcblx0XHRcdC8vLS0tIFVucHJvY2Vzc2FibGUgZW50aXR5XG5cdFx0XHRlcnJvciA9IHJlc3BvbnNlLmVycm9yO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGVycm9yID0ge1xuXHRcdFx0XHRjb2RlIDogcmVzcG9uc2Uuc3RhdHVzLnRvU3RyaW5nKCksXG5cdFx0XHRcdGVycm9yOiByZXNwb25zZS5lcnJvci50b1N0cmluZygpXG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdHRoaXMuZXZlbnRCdXNTZXJ2aWNlLmVtaXRUb0Vycm9yKGVycm9yKTtcblxuXHRcdHJldHVybiB0aHJvd0Vycm9yKGVycm9yKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgc2hvd0xvYWRlcigpOiB2b2lkIHtcblxuXHRcdGlmICgrK3RoaXMub3BlblJlcXVlc3RzID09IDEpIHtcblx0XHRcdHRoaXMuZXZlbnRCdXNTZXJ2aWNlLmVtaXRUb0FwcChuZXcgQXBwRXZlbnQoQXBwRXZlbnQuU1VCTUlUX1NUQVJUKSk7XG5cdFx0fVxuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBoaWRlTG9hZGVyKCk6IHZvaWQge1xuXG5cdFx0aWYgKC0tdGhpcy5vcGVuUmVxdWVzdHMgPT0gMCkge1xuXHRcdFx0dGhpcy5ldmVudEJ1c1NlcnZpY2UuZW1pdFRvQXBwKG5ldyBBcHBFdmVudChBcHBFdmVudC5TVUJNSVRfRU5EKSk7XG5cdFx0fVxuXHR9XG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtJbmplY3RhYmxlfSAgZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7SHR0cFNlcnZpY2V9IGZyb20gXCIuL2h0dHAtc2VydmljZVwiO1xuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBMYWJlbFNlcnZpY2Uge1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBWYXJpYWJsZXNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHJpdmF0ZSBzdGF0aWMgVE9PTEtJVF9GSUxFICAgICA6IHN0cmluZyA9IFwidG9vbGtpdFwiO1xuXHRwcml2YXRlIHN0YXRpYyBBUFBMSUNBVElPTl9GSUxFIDogc3RyaW5nID0gXCJhcHBsaWNhdGlvblwiO1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgbGFiZWxTZXQgOiBNYXA8U3RyaW5nLCBNYXA8c3RyaW5nLCBhbnk+Pjtcblx0cHJpdmF0ZSBsYW5ndWFnZSA6IHN0cmluZztcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIGxhbmd1YWdlcyA6IHN0cmluZ1tdID0gWyBcImVuXCIsIFwiaXRcIiBdO1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBDb25zdHJ1Y3RvclxuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIGh0dHBTZXJ2aWNlIDogSHR0cFNlcnZpY2UpIHtcblxuXHRcdHRoaXMubGFiZWxTZXQgPSBuZXcgTWFwKCk7XG5cdFx0dGhpcy5sYW5ndWFnZSA9IFwiZW5cIjtcblxuXHRcdC8vLS0tIExvYWQgbGFuZ3VhZ2UgZmlsZXNcblxuXHRcdHRoaXMubGFuZ3VhZ2VzLmZvckVhY2goIChsYW5ndWFnZSA6IHN0cmluZykgPT4ge1xuXHRcdFx0dGhpcy5pbml0TGFuZ3VhZ2UobGFuZ3VhZ2UpO1xuXHRcdH0pO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIEFQSSBtZXRob2RzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBzZXRMYW5ndWFnZShsYW5ndWFnZSA6IHN0cmluZykgOiB2b2lkIHtcblx0XHR0aGlzLmxhbmd1YWdlID0gbGFuZ3VhZ2U7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgZ2V0TGFiZWwoZW50aXR5IDogc3RyaW5nLCBjb2RlIDogc3RyaW5nKSA6IGFueSB7XG5cblx0XHRpZiAoY29kZSA9PSBudWxsKSB7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cblx0XHRsZXQgZW50aXR5U2V0ID0gdGhpcy5nZXRNYXBwaW5nKGVudGl0eSk7XG5cblx0XHRpZiAoZW50aXR5U2V0ID09IG51bGwpIHtcblx0XHRcdHJldHVybiBcIj9cIitlbnRpdHkrXCI/XCI7XG5cdFx0fVxuXG5cdFx0bGV0IGxhYmVsID0gZW50aXR5U2V0W2NvZGVdO1xuXG5cdFx0aWYgKGxhYmVsID09IG51bGwpIHtcblx0XHRcdHJldHVybiBlbnRpdHkrXCIuP1wiKyBjb2RlICtcIj9cIjtcblx0XHR9XG5cblx0XHRyZXR1cm4gbGFiZWw7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgZ2V0TWFwcGluZyhlbnRpdHkgOiBzdHJpbmcpIDogT2JqZWN0IHtcblxuXHRcdGxldCBsYWJlbHMgPSB0aGlzLmxhYmVsU2V0LmdldCh0aGlzLmxhbmd1YWdlKTtcblxuXHRcdGlmIChsYWJlbHMgIT0gbnVsbCkge1xuXHRcdFx0cmV0dXJuIGxhYmVscy5nZXQoZW50aXR5KTtcblx0XHR9XG5cblx0XHQvLy0tLSBQcm9iYWJseSwgd2UgYXJlIHN0aWxsIGxvYWRpbmcgZGF0YVxuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFByaXZhdGUgbWV0aG9kc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIGluaXRMYW5ndWFnZShsYW5ndWFnZSA6IHN0cmluZykgOiB2b2lkIHtcblxuXHRcdHRoaXMubG9hZExhbmd1YWdlRmlsZShsYW5ndWFnZSwgTGFiZWxTZXJ2aWNlLlRPT0xLSVRfRklMRSk7XG5cdFx0dGhpcy5sb2FkTGFuZ3VhZ2VGaWxlKGxhbmd1YWdlLCBMYWJlbFNlcnZpY2UuQVBQTElDQVRJT05fRklMRSk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwcml2YXRlIGxvYWRMYW5ndWFnZUZpbGUobGFuZ3VhZ2UgOiBzdHJpbmcsIG5hbWUgOiBzdHJpbmcpIHtcblxuXHRcdGxldCBmaWxlIDogc3RyaW5nID0gbmFtZSArXCItXCIrIGxhbmd1YWdlICtcIi5qc29uXCI7XG5cblx0XHR0aGlzLmh0dHBTZXJ2aWNlLmdldE9iamVjdChcImFzc2V0L2xhbmcvXCIrIGZpbGUpXG5cdFx0XHRcdFx0XHQuc3Vic2NyaWJlKFx0cmVzdWx0ID0+IHRoaXMucHJvY2Vzc0ZpbGUobGFuZ3VhZ2UsIGZpbGUsIHJlc3VsdCksXG5cdFx0XHRcdFx0XHRcdFx0XHRlcnJvciA9PiBjb25zb2xlLmxvZyhcIkNhbm5vdCBsb2FkIGxhYmVscyBmaWxlIDogXCIrIGZpbGUpKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHByaXZhdGUgcHJvY2Vzc0ZpbGUobGFuZ3VhZ2UgOiBzdHJpbmcsIGZpbGU6c3RyaW5nLCBkYXRhIDogT2JqZWN0KSA6IHZvaWQge1xuXG5cdFx0Y29uc29sZS5sb2coXCJMb2FkZWQgbGFiZWxzIGZpbGUgOiBcIisgZmlsZSk7XG5cblx0XHRsZXQgbGFiZWxzID0gdGhpcy5sYWJlbFNldC5nZXQobGFuZ3VhZ2UpO1xuXG5cdFx0aWYgKGxhYmVscyA9PSBudWxsKSB7XG5cdFx0XHRsYWJlbHMgPSBuZXcgTWFwKCk7XG5cdFx0XHR0aGlzLmxhYmVsU2V0LnNldChsYW5ndWFnZSwgbGFiZWxzKTtcblx0XHR9XG5cblx0XHRmb3IgKGxldCBrZXkgaW4gZGF0YSkge1xuXHRcdFx0bGFiZWxzLnNldChrZXksIGRhdGFba2V5XSk7XG5cdFx0fVxuXHR9XG59XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIsIi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vPT09XG4vLz09PSAoQykgQ29weXJpZ2h0IDIwMTggSGV3bGV0dCBQYWNrYXJkIEVudGVycHJpc2UgRGV2ZWxvcG1lbnQgTFAuXG4vLz09PVxuLy89PT0gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbi8vPT09IGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGVcbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtNZXNzYWdlU2VydmljZX0gZnJvbSAncHJpbWVuZy9jb21wb25lbnRzL2NvbW1vbi9tZXNzYWdlc2VydmljZSc7XG5cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5vdGlmaWNhdGlvblNlcnZpY2Uge1xuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLy0tLVxuXHQvLy0tLSBDb25zdHJ1Y3RvclxuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIG1lc3NhZ2VTZXJ2aWNlOk1lc3NhZ2VTZXJ2aWNlKSB7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQVBJIG1ldGhvZHNcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHNob3dTdWNjZXNzKHRpdGxlIDogc3RyaW5nLCBtZXNzYWdlIDogc3RyaW5nKSA6IHZvaWQge1xuXHRcdHRoaXMuc2hvdygnc3VjY2VzcycsIHRpdGxlLCBtZXNzYWdlKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBzaG93SW5mbyh0aXRsZSA6IHN0cmluZywgbWVzc2FnZSA6IHN0cmluZykgOiB2b2lkIHtcblx0XHR0aGlzLnNob3coJ2luZm8nLCB0aXRsZSwgbWVzc2FnZSk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgc2hvd1dhcm4odGl0bGUgOiBzdHJpbmcsIG1lc3NhZ2UgOiBzdHJpbmcpIDogdm9pZCB7XG5cdFx0dGhpcy5zaG93KCd3YXJuJywgdGl0bGUsIG1lc3NhZ2UpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHNob3dFcnJvcih0aXRsZSA6IHN0cmluZywgbWVzc2FnZSA6IHN0cmluZykgOiB2b2lkIHtcblx0XHR0aGlzLnNob3coJ2Vycm9yJywgdGl0bGUsIG1lc3NhZ2UpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0cHVibGljIHNob3coc2V2ZXJpdHkgOiBzdHJpbmcsIHRpdGxlIDogc3RyaW5nLCBtZXNzYWdlIDogc3RyaW5nKSA6IHZvaWQge1xuXG5cdFx0dGhpcy5tZXNzYWdlU2VydmljZS5hZGQoIHtcblx0XHRcdHNldmVyaXR5OiBzZXZlcml0eSxcblx0XHRcdHN1bW1hcnkgOiB0aXRsZSxcblx0XHRcdGRldGFpbCAgOiBtZXNzYWdlXG5cdFx0fSk7XG5cdH1cbn1cblxuLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIiwiLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy89PT1cbi8vPT09IChDKSBDb3B5cmlnaHQgMjAxOCBIZXdsZXR0IFBhY2thcmQgRW50ZXJwcmlzZSBEZXZlbG9wbWVudCBMUC5cbi8vPT09XG4vLz09PSBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuLy89PT0gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZVxuLy89PT1cbi8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuaW1wb3J0IHtJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtBcHBFdmVudH0gICAgICAgICAgIGZyb20gXCJAaHBlL2FuZ3VsYXItdG9vbGtpdC9tb2RlbFwiO1xuaW1wb3J0IHtDcmVkZW50aWFsc30gICAgICAgIGZyb20gXCJAaHBlL2FuZ3VsYXItdG9vbGtpdC9tb2RlbFwiO1xuaW1wb3J0IHtQcm9maWxlfSAgICAgICAgICAgIGZyb20gXCJAaHBlL2FuZ3VsYXItdG9vbGtpdC9tb2RlbFwiO1xuaW1wb3J0IHtTZXNzaW9ufSAgICAgICAgICAgIGZyb20gXCJAaHBlL2FuZ3VsYXItdG9vbGtpdC9tb2RlbFwiO1xuaW1wb3J0IHtTZXNzaW9uVXNlcn0gICAgICAgIGZyb20gXCJAaHBlL2FuZ3VsYXItdG9vbGtpdC9tb2RlbFwiO1xuXG5pbXBvcnQge0Fic3RyYWN0U3Vic2NyaWJlcn0gZnJvbSBcIi4vYWJzdHJhY3Qtc3Vic2NyaWJlclwiO1xuaW1wb3J0IHtFdmVudEJ1c1NlcnZpY2V9ICAgIGZyb20gXCIuL2V2ZW50YnVzLXNlcnZpY2VcIjtcbmltcG9ydCB7SHR0cFNlcnZpY2V9ICAgICAgICBmcm9tIFwiLi9odHRwLXNlcnZpY2VcIjtcblxuXG4vLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBTZXNzaW9uU2VydmljZSBleHRlbmRzIEFic3RyYWN0U3Vic2NyaWJlciB7XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIFZhcmlhYmxlc1xuXHQvLy0tLVxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRwdWJsaWMgc2Vzc2lvbiAgICAgOiBTZXNzaW9uO1xuXHRwdWJsaWMgdG9rZW4gICAgICAgOiBzdHJpbmc7XG5cdHB1YmxpYyB1c2VyICAgICAgICA6IFNlc3Npb25Vc2VyO1xuXHRwdWJsaWMgcHJvZmlsZSAgICAgOiBQcm9maWxlO1xuXHRwdWJsaWMgcGVybWlzc2lvbnMgOiBNYXA8c3RyaW5nLCBib29sZWFuPjtcblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8tLS1cblx0Ly8tLS0gQ29uc3RydWN0b3Jcblx0Ly8tLS1cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Y29uc3RydWN0b3IoZXZlbnRCdXNTZXJ2aWNlOiBFdmVudEJ1c1NlcnZpY2UsIHByaXZhdGUgaHR0cFNlcnZpY2UgOiBIdHRwU2VydmljZSkge1xuXG5cdFx0c3VwZXIoZXZlbnRCdXNTZXJ2aWNlKTtcblx0XHR0aGlzLmNsZWFyU2Vzc2lvbigpO1xuXG5cdFx0c3VwZXIuc3Vic2NyaWJlVG9BcHAoQXBwRXZlbnQuSU5WQUxJRF9UT0tFTiwgZXZlbnQgPT4gdGhpcy5vbkludmFsaWRUb2tlbihldmVudCkpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vLS0tXG5cdC8vLS0tIEFQSSBtZXRob2RzXG5cdC8vLS0tXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdHB1YmxpYyBsb2dpbihjcmVkIDogQ3JlZGVudGlhbHMpIDogdm9pZCB7XG5cblx0XHRjb25zb2xlLmxvZyhcIlNlc3Npb25TZXJ2aWNlLmxvZ2luIDogTG9nZ2luZyBpbiB1c2VyPSdcIiArIGNyZWQudXNlcm5hbWUgKyBcIidcIik7XG5cblx0XHQvLy0t