A self hosted chat application with end-to-end encrypted messaging.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

614 lines
78 KiB

(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("../model/AbstractModel");
require("../model/UserModel");
require("../view/AbstractView");
require("../view/UserView");
const ChatMessageViewModel_1 = require("../viewmodel/ChatMessageViewModel");
class ChatController {
constructor(model, view) {
this._model = model;
this._view = view;
}
/**
* eventHandler
*/
eventHandler(vm) {
this._model.someBusinessMethod(vm);
}
test() {
const chatMessageViewModels = [];
let chatMessageViewModelMock = new ChatMessageViewModel_1.ChatMessageViewModel();
chatMessageViewModelMock.fromUser = "user1";
chatMessageViewModelMock.toUser = "user2";
chatMessageViewModelMock.message = "";
chatMessageViewModelMock.messageTime = new Date();
chatMessageViewModels.push(chatMessageViewModelMock);
}
}
exports.ChatController = ChatController;
},{"../model/AbstractModel":4,"../model/UserModel":8,"../view/AbstractView":12,"../view/UserView":14,"../viewmodel/ChatMessageViewModel":16}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("../model/AbstractModel");
require("../model/UserModel");
require("../view/AbstractView");
require("../view/UserView");
const ActiveUserViewModel_1 = require("../viewmodel/ActiveUserViewModel");
class UserController {
constructor(model, view) {
this._model = model;
this._view = view;
}
/**
* eventHandler
*/
eventHandler(vm) {
this._model.someBusinessMethod(vm);
}
test() {
const activeUsersMock = [];
let activeUserViewModelMock = new ActiveUserViewModel_1.ActiveUserViewModel();
activeUserViewModelMock.userName = "some user";
activeUserViewModelMock.lastActive = "3 hrs ago";
activeUserViewModelMock.online = true;
activeUsersMock.push(activeUserViewModelMock);
activeUserViewModelMock = new ActiveUserViewModel_1.ActiveUserViewModel();
activeUserViewModelMock.lastActive = "3 hrs ago";
activeUserViewModelMock.online = true;
activeUserViewModelMock.userName = "some user 2";
activeUsersMock.push(activeUserViewModelMock);
this.eventHandler(activeUsersMock);
}
}
exports.UserController = UserController;
},{"../model/AbstractModel":4,"../model/UserModel":8,"../view/AbstractView":12,"../view/UserView":14,"../viewmodel/ActiveUserViewModel":15}],3:[function(require,module,exports){
(function (global){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const UserModel_1 = require("./model/UserModel");
const UserView_1 = require("./view/UserView");
const UserController_1 = require("./controller/UserController");
const Handlebars = (typeof window !== "undefined" ? window['Handlebars'] : typeof global !== "undefined" ? global['Handlebars'] : null);
const markdownit = (typeof window !== "undefined" ? window['markdownit'] : typeof global !== "undefined" ? global['markdownit'] : null);
const ChatModel_1 = require("./model/ChatModel");
const ChatView_1 = require("./view/ChatView");
const ChatController_1 = require("./controller/ChatController");
const JsonAPI_1 = require("./singleton/JsonAPI");
// import log = require('loglevel')
const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null);
const SJCLEncryptionService_1 = require("./service/SJCLEncryptionService");
// var markdownit = require('markdown-it');
var md = new markdownit();
const userBox = document.getElementById('contacts-box');
log.setLevel("TRACE");
const chatModel = new ChatModel_1.ChatModel();
const userModel = new UserModel_1.UserModel();
// const userModel = ModelFactory.createModel("USER");
// @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'.
const userView = new UserView_1.UserView(userModel, chatModel, userBox);
// console.log(userBox);
userModel.attach(userView);
// userView.model
const userController = new UserController_1.UserController(userModel, userView);
userController.test();
// userModel.someBusinessMethod(activeUsersMock);
log.info("hello");
const chatArea = document.getElementById('chat-area-new');
// @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'.
const chatView = new ChatView_1.ChatView(chatModel, chatArea);
const chatController = new ChatController_1.ChatController(chatModel, chatView);
function someFunc(vm) {
// log.info(vm);
// logger.info(vm)
}
log.info("test");
// someFunc(activeUserViewModelMock);
// @ts-ignore: Object is possibly 'null'.
var source = document.getElementById("msg_container_template").innerHTML;
var msgContainerTemplate = Handlebars.compile(source);
JsonAPI_1.JsonAPI.ACTIVE_USERS_GET + 'aef';
const encryptionService = new SJCLEncryptionService_1.SJCLEncryptionService();
let ct = encryptionService.encrypt("password", "data");
console.log(encryptionService.decrypt("password", ct));
Handlebars.registerHelper('avatar', function () {
return '<div class="img_cont_msg"> <img src="https://static.turbosquid.com/Preview/001292/481/WV/_D.jpg" class="rounded-circle user_img_msg"> </div>';
});
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./controller/ChatController":1,"./controller/UserController":2,"./model/ChatModel":5,"./model/UserModel":8,"./service/SJCLEncryptionService":9,"./singleton/JsonAPI":10,"./view/ChatView":13,"./view/UserView":14}],4:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
},{}],5:[function(require,module,exports){
(function (global){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null);
const ChatModelHelper_1 = require("./ChatModelHelper");
class ChatModel {
constructor() {
/**
* @type {Observer[]} List of subscribers. In real life, the list of
* subscribers can be stored more comprehensively (categorized by event
* type, etc.).
*/
this._observers = [];
this.state = null;
this._messagesMap = new Map();
}
/**
* The subscription management methods.
*/
attach(observer) {
console.log('Subject: Attached an observer.');
this._observers.push(observer);
}
detach(observer) {
const observerIndex = this._observers.indexOf(observer);
this._observers.splice(observerIndex, 1);
console.log('Subject: Detached an observer.');
}
setUserMessages(username, messages) {
this._messagesMap.set(username, messages);
}
/**
* Trigger an update in each subscriber.
*/
notify() {
console.log('Subject: Notifying observers...');
for (const observer of this._observers) {
observer.update(this.state);
}
}
someBusinessMethod(chatMessageList) {
this.state = chatMessageList;
this.helperMethod();
console.log(`Subject: My state has just changed`);
console.log(chatMessageList);
this.notify();
}
getmessages(userName, passphrase, lastMessageTime) {
const cVMs = ChatModelHelper_1.ChatModelHelper.getMessages(userName, passphrase, lastMessageTime, this);
if (cVMs != null) {
log.info('Subject: My state has just changed');
log.debug(cVMs);
this._messagesMap.set(userName, cVMs);
this.notify();
}
else {
log.error('Messages were null');
}
}
helperMethod() { }
populateMessages() {
}
}
exports.ChatModel = ChatModel;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./ChatModelHelper":6}],6:[function(require,module,exports){
(function (global){
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null);
const ChatMessageViewModel_1 = require("../viewmodel/ChatMessageViewModel");
const JsonAPI_1 = require("../singleton/JsonAPI");
const FetchErrorHandler_1 = require("./FetchErrorHandler");
const SJCLEncryptionService_1 = require("../service/SJCLEncryptionService");
class ChatModelHelper {
static getMessages(userName, passphrase, lastMessageTime, chatModel) {
switch (lastMessageTime) {
case null: {
this.getAllMessagesAjax(userName)
.then((data) => {
log.debug(`Subject: received all messages`);
// let userNames = data.map(ChatMessageViewModel => ChatMessageViewModel.fromUser)
// let sumt = data.map(chatMessageViewModel => { return this.encryptionService.decrypt(passphrase, chatMessageViewModel.messageCipher) });
return data.map(vm => this.toChatMessageVM(vm, passphrase));
// chatModel.setUserMessages(userName, chatMessageVMs);
// chatModel.notify();
});
break;
}
default: {
this.getNewMessagesAjax(userName, lastMessageTime)
.then((data) => {
log.debug(`Subject: received new messages`);
return data.map(vm => this.toChatMessageVM(vm, passphrase));
// chatModel.setUserMessages(userName, chatMessageVMs);
// this.state = data;
// chatModel.notify();
});
break;
}
}
return null;
}
static toChatMessageVM(chatMessageDTO, passphrase) {
const vm = new ChatMessageViewModel_1.ChatMessageViewModel();
vm.fromUser = chatMessageDTO.fromUser;
vm.toUser = chatMessageDTO.toUser;
vm.messageTime = chatMessageDTO.messageTime;
vm.message = this.encryptionService.decrypt(passphrase, chatMessageDTO.messageCipher);
return vm;
}
static getAllMessagesAjax(toUser) {
return __awaiter(this, void 0, void 0, function* () {
let headers = new Headers();
if (JsonAPI_1.JsonAPI.authToken == null) {
log.error("authToken null");
return;
}
;
headers.append('X-AUTH-TOKEN', JsonAPI_1.JsonAPI.authToken);
let response = yield fetch(`${JsonAPI_1.JsonAPI.CHAT_MESSAGES_GET}/${toUser}`, {
method: 'GET',
headers: headers
});
console.log(response.clone());
if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) {
return null;
}
let data = yield response.json();
return data;
});
}
static getNewMessagesAjax(toUser, lastMessageTimeStamp) {
return __awaiter(this, void 0, void 0, function* () {
let headers = new Headers();
if (JsonAPI_1.JsonAPI.authToken == null) {
log.error("authToken null");
return;
}
;
headers.append('X-AUTH-TOKEN', JsonAPI_1.JsonAPI.authToken);
let response = yield fetch(`${JsonAPI_1.JsonAPI.CHAT_MESSAGES_GET}/${toUser}/${lastMessageTimeStamp}`, {
method: 'GET',
headers: headers
});
console.log(response.clone());
if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) {
return null;
}
let data = yield response.json();
return data;
});
}
}
exports.ChatModelHelper = ChatModelHelper;
ChatModelHelper.encryptionService = new SJCLEncryptionService_1.SJCLEncryptionService();
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../service/SJCLEncryptionService":9,"../singleton/JsonAPI":10,"../viewmodel/ChatMessageViewModel":16,"./FetchErrorHandler":7}],7:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function fetchErrorHandler(response) {
// alertify.success('Current position : ' + alertify.get('notifier', 'position'));
if (!response.ok) {
return response.text().catch(err => {
// the status was not ok and there is no json body
// throw new Error(response.statusText);
// window.alert(sprintf('Some error occured. Http code is %s', response.status));
// alertify.error(sprintf('Some error occured. Http code is %s', response.status));
return true;
}).then(json => {
// the status was not ok but there is a json body
// throw new Error(json.error.message); // example error message returned by a REST API
// window.alert(sprintf('Error: %s (Http code %s)', json, response.status));
// alertify.error(sprintf('Some error occured. Http code is %s', response.status));
console.log(json);
return true;
});
}
}
exports.fetchErrorHandler = fetchErrorHandler;
},{}],8:[function(require,module,exports){
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const FetchErrorHandler_1 = require("./FetchErrorHandler");
const JsonAPI_1 = require("../singleton/JsonAPI");
class UserModel {
// @ts-ignore: Cannot find name 'hostAddress'.
constructor() {
/**
* @type {Observer[]} List of subscribers. In real life, the list of
* subscribers can be stored more comprehensively (categorized by event
* type, etc.).
*/
this.observers = [];
}
/**
* The subscription management methods.
*/
attach(observer) {
console.log('Subject: Attached an observer.');
this.observers.push(observer);
}
detach(observer) {
const observerIndex = this.observers.indexOf(observer);
this.observers.splice(observerIndex, 1);
console.log('Subject: Detached an observer.');
}
/**
* Trigger an update in each subscriber.
*/
notify() {
console.log('Subject: Notifying observers...');
for (const observer of this.observers) {
observer.update(this.state);
}
}
someBusinessMethod(activeuserList) {
this.state = activeuserList;
this.helperMethod();
console.log(`Subject: My state has just changed`);
console.log(activeuserList);
this.notify();
}
/**
* getActiveUsers
*/
getActiveUsers() {
this.getActiveUsersAjax("", JsonAPI_1.JsonAPI.ACTIVE_USERS_GET)
.then(data => {
// // activeUsers = data;
// sessionStorage.setItem('activeUsers', JSON.stringify(data));
// console.log(sessionStorage.getItem('activeUsers'));
console.log(`Subject: received ajax active users`);
this.state = data;
this.notify();
});
}
getActiveUsersAjax(authToken2, URL) {
return __awaiter(this, void 0, void 0, function* () {
let headers = new Headers();
// headers.append('Authorization', basicAuthToken);
headers.append('X-AUTH-TOKEN', authToken2);
let response = yield fetch(JsonAPI_1.JsonAPI.ACTIVE_USERS_GET, {
method: 'GET',
headers: headers
});
console.log(response.clone());
if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) {
return null;
}
let data = yield response.json();
// return data;
return new Promise((resolve, reject) => {
if (data != null)
resolve(data);
else
reject('Response data null');
});
});
}
helperMethod() { }
}
exports.UserModel = UserModel;
},{"../singleton/JsonAPI":10,"./FetchErrorHandler":7}],9:[function(require,module,exports){
(function (global){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sjcl = (typeof window !== "undefined" ? window['sjcl'] : typeof global !== "undefined" ? global['sjcl'] : null);
class SJCLEncryptionService {
constructor() {
this.params = { mode: "gcm", ts: 128, adata: "", iter: 10000 };
}
encrypt(passphrase, plainText) {
return sjcl.encrypt(passphrase, plainText, this.params);
}
decrypt(passphrase, cipher) {
return sjcl.decrypt(passphrase, cipher, undefined, undefined);
}
}
exports.SJCLEncryptionService = SJCLEncryptionService;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],10:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var JsonAPI;
(function (JsonAPI) {
// @ts-ignore: Cannot find name 'hostAddress'.
JsonAPI.userName = localStorage.getItem('userName');
JsonAPI.authToken = localStorage.getItem('authToken');
JsonAPI.ACTIVE_USERS_GET = `/api/chat/get/active-users`;
JsonAPI.CHAT_MESSAGES_GET = ``;
})(JsonAPI = exports.JsonAPI || (exports.JsonAPI = {}));
},{}],11:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class TemplateFactory {
// static getTemplate(templateName: string): Handlebars.TemplateDelegate<any> {
// switch (templateName) {
// case "user-contact-online-template": {
// // let source = document.getElementById("user-contact-online-template").innerHTML;
// // let msgContainerTemplate = Handlebars.compile(source);
// // return msgContainerTemplate;
// return this.createTemplate(templateName);
// }
// case "msg_container_send_template": {
// // let source = document.getElementById("msg_container_send_template").innerHTML;
// // let msgContainerTemplate = Handlebars.compile(source);
// // return msgContainerTemplate;
// return this.createTemplate(templateName);
// }
// case "msg_container_template": {
// // let source = document.getElementById("msg_container_send_template").innerHTML;
// // let msgContainerTemplate = Handlebars.compile(source);
// // return msgContainerTemplate;
// return this.createTemplate(templateName);
// }
// default:
// throw new Error('invalid template name');
// }
// }
static getTemplate(templateName) {
//@ts-ignore: Object is possibly 'null'.
let source = document.getElementById(templateName).innerHTML;
let msgContainerTemplate = Handlebars.compile(source);
return msgContainerTemplate;
}
}
exports.TemplateFactory = TemplateFactory;
},{}],12:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
},{}],13:[function(require,module,exports){
(function (global){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const TemplateFactory_1 = require("../template/TemplateFactory");
const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null);
class ChatView {
constructor(model, element) {
this._messageSendTemplate = TemplateFactory_1.TemplateFactory.getTemplate('msg_container_send_template');
this._model = model;
this._element = element;
}
update(data) {
let html = "";
data.forEach((vm) => {
html += this._messageSendTemplate(vm);
});
this._element.innerHTML = html;
log.debug(this._element.innerHTML);
}
}
exports.ChatView = ChatView;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../template/TemplateFactory":11}],14:[function(require,module,exports){
(function (global){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const TemplateFactory_1 = require("../template/TemplateFactory");
const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null);
class UserView {
// private userBoxes: any[] = [];
constructor(model, chatModel, element) {
this._model = model;
this._chatModel = chatModel;
this._element = element;
}
update(data) {
let template = TemplateFactory_1.TemplateFactory.getTemplate('user-contact-online-template');
let html = "";
data.forEach((element) => {
html += template(element);
});
this._element.innerHTML = html;
this.addUserCallBacks();
console.log(this._element.innerHTML);
}
helper() {
}
addUserCallBacks() {
let userBoxes = document.getElementsByClassName('user-box');
for (let i = 0; i < userBoxes.length; i++) {
let userBox = userBoxes[i];
userBoxes[i].addEventListener('click', this.userCallBack.bind(this, userBox));
}
}
userCallBack(el) {
let current = document.getElementsByClassName('user-box active');
let passphrase = '';
if (current.length > 0) {
let passphraseInput = document.getElementById('passphrase');
if (passphraseInput == null) {
log.error('passphraseInput element reference is null');
return;
}
passphrase = passphraseInput.value;
if (passphrase == '' || passphrase == null) {
// alert('Please input passphrase')
// alertify.error('Please enter a passphrase');
log.error('passphrase is empty or null');
return;
}
current[0].className = current[0].className.replace(" active", "");
}
// Add the active class to the current/clicked button
else if (current.length == 0) {
let elem = document.getElementById('passphrase-initial');
if (elem == null) {
log.error('passphraseInput element reference is null');
return;
}
passphrase = elem.value;
if (passphrase == '' || passphrase == null) {
// // alert('Please input passphrase')
// // alertify.error('Please enter a passphrase');
log.error('passphrase is empty or null');
return;
}
// @ts-ignore: Object is possibly 'null'.
document.getElementById('no-user-selected').hidden = true;
// @ts-ignore: Object is possibly 'null'.
document.getElementById('chat-card').hidden = false;
// @ts-ignore: Object is possibly 'null'.
elem.hidden = true;
}
// console.log(this.getElementsByClassName('to-user-span'));
let elem = el.getElementsByClassName('to-user-span')[0];
let userName = elem.innerText;
// @ts-ignore: Object is possibly 'null'.
document.getElementById('user-name-span').innerText = userName;
this._chatModel.getmessages(userName, passphrase, null);
// populateMessages(userName, passphrase);
sessionStorage.setItem('selectedUser', userName);
el.className += " active";
}
}
exports.UserView = UserView;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../template/TemplateFactory":11}],15:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class ActiveUserViewModel {
}
exports.ActiveUserViewModel = ActiveUserViewModel;
},{}],16:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class ChatMessageViewModel {
}
exports.ChatMessageViewModel = ChatMessageViewModel;
},{}]},{},[3])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJ0cy9zcmMvY29udHJvbGxlci9DaGF0Q29udHJvbGxlci50cyIsInRzL3NyYy9jb250cm9sbGVyL1VzZXJDb250cm9sbGVyLnRzIiwidHMvc3JjL21haW4udHMiLCJ0cy9zcmMvbW9kZWwvQ2hhdE1vZGVsLnRzIiwidHMvc3JjL21vZGVsL0NoYXRNb2RlbEhlbHBlci50cyIsInRzL3NyYy9tb2RlbC9GZXRjaEVycm9ySGFuZGxlci50cyIsInRzL3NyYy9tb2RlbC9Vc2VyTW9kZWwudHMiLCJ0cy9zcmMvc2VydmljZS9TSkNMRW5jcnlwdGlvblNlcnZpY2UudHMiLCJ0cy9zcmMvc2luZ2xldG9uL0pzb25BUEkudHMiLCJ0cy9zcmMvdGVtcGxhdGUvVGVtcGxhdGVGYWN0b3J5LnRzIiwidHMvc3JjL3ZpZXcvQ2hhdFZpZXcudHMiLCJ0cy9zcmMvdmlldy9Vc2VyVmlldy50cyIsInRzL3NyYy92aWV3bW9kZWwvQWN0aXZlVXNlclZpZXdNb2RlbC50cyIsInRzL3NyYy92aWV3bW9kZWwvQ2hhdE1lc3NhZ2VWaWV3TW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztBQ0NBLGtDQUErQjtBQUMvQiw4QkFBMkI7QUFDM0IsZ0NBQTZCO0FBQzdCLDRCQUF5QjtBQUd6Qiw0RUFBeUU7QUFJekUsTUFBYSxjQUFjO0lBS3ZCLFlBQVksS0FBZ0IsRUFBRSxJQUFjO1FBQ3hDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7SUFHRDs7T0FFRztJQUNJLFlBQVksQ0FBQyxFQUEwQjtRQUMxQyxJQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLENB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RCx5Q0FBeUM7WUFDekMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1lBQ3BELHlDQUF5QztZQUN6QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztTQUN0QjtRQUNELDREQUE0RDtRQUM1RCxJQUFJLElBQUksR0FBRyxFQUFFLENBQUMsc0JBQXNCLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFnQixDQUFDO1FBQ3ZFLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDOUIseUNBQXlDO1FBQ3pDLFFBQVEsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO1FBQy9ELElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDeEQsMENBQTBDO1FBQzFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELEVBQUUsQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDO0lBQzlCLENBQUM7Q0FFSjtBQTlGRCw0QkE4RkM7Ozs7Ozs7QUN4R0QsTUFBYSxtQkFBbUI7Q0FJL0I7QUFKRCxrREFJQzs7Ozs7QUNKRCxNQUFhLG9CQUFvQjtDQU9oQztBQVBELG9EQU9DIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiaW1wb3J0IHsgQ29udHJvbGxlciB9IGZyb20gXCIuL0Fic3RyYWN0Q29udHJvbGxlclwiO1xuaW1wb3J0IFwiLi4vbW9kZWwvQWJzdHJhY3RNb2RlbFwiXG5pbXBvcnQgXCIuLi9tb2RlbC9Vc2VyTW9kZWxcIlxuaW1wb3J0IFwiLi4vdmlldy9BYnN0cmFjdFZpZXdcIlxuaW1wb3J0IFwiLi4vdmlldy9Vc2VyVmlld1wiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9BYnN0cmFjdE1vZGVsXCI7XG5pbXBvcnQgeyBWaWV3IH0gZnJvbSBcIi4uL3ZpZXcvQWJzdHJhY3RWaWV3XCI7XG5pbXBvcnQgeyBDaGF0TWVzc2FnZVZpZXdNb2RlbCB9IGZyb20gXCIuLi92aWV3bW9kZWwvQ2hhdE1lc3NhZ2VWaWV3TW9kZWxcIjtcbmltcG9ydCB7IENoYXRNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9DaGF0TW9kZWxcIjtcbmltcG9ydCB7IENoYXRWaWV3IH0gZnJvbSBcIi4uL3ZpZXcvQ2hhdFZpZXdcIjtcblxuZXhwb3J0IGNsYXNzIENoYXRDb250cm9sbGVyIHtcbiAgICBwcml2YXRlIF9tb2RlbDogQ2hhdE1vZGVsO1xuICAgIHByaXZhdGUgX3ZpZXc6IENoYXRWaWV3O1xuXG5cbiAgICBjb25zdHJ1Y3Rvcihtb2RlbDogQ2hhdE1vZGVsLCB2aWV3OiBDaGF0Vmlldykge1xuICAgICAgICB0aGlzLl9tb2RlbCA9IG1vZGVsO1xuICAgICAgICB0aGlzLl92aWV3ID0gdmlldztcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIGV2ZW50SGFuZGxlclxuICAgICAqL1xuICAgIHB1YmxpYyBldmVudEhhbmRsZXIodm06IENoYXRNZXNzYWdlVmlld01vZGVsW10pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fbW9kZWwuc29tZUJ1c2luZXNzTWV0aG9kKHZtKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdGVzdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2hhdE1lc3NhZ2VWaWV3TW9kZWxzOiBDaGF0TWVzc2FnZVZpZXdNb2RlbFtdID0gW107XG4gICAgICAgIGxldCBjaGF0TWVzc2FnZVZpZXdNb2RlbE1vY2sgPSBuZXcgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwoKTtcbiAgICAgICAgY2hhdE1lc3NhZ2VWaWV3TW9kZWxNb2NrLmZyb21Vc2VyID0gXCJ1c2VyMVwiO1xuICAgICAgICBjaGF0TWVzc2FnZVZpZXdNb2RlbE1vY2sudG9Vc2VyID0gXCJ1c2VyMlwiO1xuICAgICAgICBjaGF0TWVzc2FnZVZpZXdNb2RlbE1vY2subWVzc2FnZSA9IFwiXCI7XG4gICAgICAgIGNoYXRNZXNzYWdlVmlld01vZGVsTW9jay5tZXNzYWdlVGltZSA9IG5ldyBEYXRlKCk7XG4gICAgICAgIGNoYXRNZXNzYWdlVmlld01vZGVscy5wdXNoKGNoYXRNZXNzYWdlVmlld01vZGVsTW9jayk7XG4gICAgfVxuXG4gICAgXG59IiwiaW1wb3J0IHsgQ29udHJvbGxlciB9IGZyb20gXCIuL0Fic3RyYWN0Q29udHJvbGxlclwiO1xuaW1wb3J0IFwiLi4vbW9kZWwvQWJzdHJhY3RNb2RlbFwiXG5pbXBvcnQgXCIuLi9tb2RlbC9Vc2VyTW9kZWxcIlxuaW1wb3J0IFwiLi4vdmlldy9BYnN0cmFjdFZpZXdcIlxuaW1wb3J0IFwiLi4vdmlldy9Vc2VyVmlld1wiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9BYnN0cmFjdE1vZGVsXCI7XG5pbXBvcnQgeyBWaWV3IH0gZnJvbSBcIi4uL3ZpZXcvQWJzdHJhY3RWaWV3XCI7XG5pbXBvcnQgeyBBY3RpdmVVc2VyVmlld01vZGVsIH0gZnJvbSBcIi4uL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsXCI7XG5pbXBvcnQgeyBVc2VyVmlldyB9IGZyb20gXCIuLi92aWV3L1VzZXJWaWV3XCI7XG5cbmV4cG9ydCBjbGFzcyBVc2VyQ29udHJvbGxlciB7XG4gICAgcHJpdmF0ZSBfbW9kZWw6IE1vZGVsO1xuICAgIHByaXZhdGUgX3ZpZXc6IFVzZXJWaWV3O1xuXG5cbiAgICBjb25zdHJ1Y3Rvcihtb2RlbDogTW9kZWwsIHZpZXc6IFVzZXJWaWV3KSB7XG4gICAgICAgIHRoaXMuX21vZGVsID0gbW9kZWw7XG4gICAgICAgIHRoaXMuX3ZpZXcgPSB2aWV3O1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogZXZlbnRIYW5kbGVyXG4gICAgICovXG4gICAgcHVibGljIGV2ZW50SGFuZGxlcih2bTogQWN0aXZlVXNlclZpZXdNb2RlbFtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX21vZGVsLnNvbWVCdXNpbmVzc01ldGhvZCh2bSk7XG4gICAgfVxuXG4gICAgcHVibGljIHRlc3QoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZVVzZXJzTW9jazogQWN0aXZlVXNlclZpZXdNb2RlbFtdID0gW107XG4gICAgICAgIGxldCBhY3RpdmVVc2VyVmlld01vZGVsTW9jayA9IG5ldyBBY3RpdmVVc2VyVmlld01vZGVsKCk7XG4gICAgICAgIGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrLnVzZXJOYW1lID0gXCJzb21lIHVzZXJcIjtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2subGFzdEFjdGl2ZSA9IFwiMyBocnMgYWdvXCI7XG4gICAgICAgIGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrLm9ubGluZSA9IHRydWU7XG4gICAgICAgIGFjdGl2ZVVzZXJzTW9jay5wdXNoKGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrKTtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2sgPSBuZXcgQWN0aXZlVXNlclZpZXdNb2RlbCgpO1xuICAgICAgICBhY3RpdmVVc2VyVmlld01vZGVsTW9jay5sYXN0QWN0aXZlID0gXCIzIGhycyBhZ29cIjtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2sub25saW5lID0gdHJ1ZTtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2sudXNlck5hbWUgPSBcInNvbWUgdXNlciAyXCI7XG4gICAgICAgIGFjdGl2ZVVzZXJzTW9jay5wdXNoKGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrKTtcbiAgICAgICAgdGhpcy5ldmVudEhhbmRsZXIoYWN0aXZlVXNlcnNNb2NrKTtcbiAgICB9XG5cbiAgICBcbn0iLCJpbXBvcnQgeyBDb250cm9sbGVyIH0gZnJvbSBcIi4vY29udHJvbGxlci9BYnN0cmFjdENvbnRyb2xsZXJcIjtcbmltcG9ydCB7IFVzZXJNb2RlbCB9IGZyb20gXCIuL21vZGVsL1VzZXJNb2RlbFwiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuL21vZGVsL0Fic3RyYWN0TW9kZWxcIjtcbmltcG9ydCB7IFZpZXcgfSBmcm9tIFwiLi92aWV3L0Fic3RyYWN0Vmlld1wiO1xuaW1wb3J0IHsgVXNlclZpZXcgfSBmcm9tIFwiLi92aWV3L1VzZXJWaWV3XCI7XG5pbXBvcnQgeyBVc2VyQ29udHJvbGxlciB9IGZyb20gXCIuL2NvbnRyb2xsZXIvVXNlckNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IE1vZGVsRmFjdG9yeSB9IGZyb20gXCIuL21vZGVsL01vZGVsRmFjdG9yeVwiO1xuaW1wb3J0IHsgQWN0aXZlVXNlclZpZXdNb2RlbCB9IGZyb20gXCIuL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsXCI7XG5pbXBvcnQgeyBDaGF0TWVzc2FnZVZpZXdNb2RlbCB9IGZyb20gXCIuL3ZpZXdtb2RlbC9DaGF0TWVzc2FnZVZpZXdNb2RlbFwiO1xuaW1wb3J0ICogYXMgSGFuZGxlYmFycyBmcm9tIFwiaGFuZGxlYmFyc1wiO1xuaW1wb3J0IG1hcmtkb3duaXQgPSByZXF1aXJlKCdtYXJrZG93bi1pdCcpO1xuaW1wb3J0IHsgQ2hhdE1vZGVsIH0gZnJvbSBcIi4vbW9kZWwvQ2hhdE1vZGVsXCI7XG5pbXBvcnQgeyBDaGF0VmlldyB9IGZyb20gXCIuL3ZpZXcvQ2hhdFZpZXdcIjtcbmltcG9ydCB7IENoYXRDb250cm9sbGVyIH0gZnJvbSBcIi4vY29udHJvbGxlci9DaGF0Q29udHJvbGxlclwiO1xuaW1wb3J0IHsgSnNvbkFQSSB9IGZyb20gXCIuL3NpbmdsZXRvbi9Kc29uQVBJXCI7XG4vLyBpbXBvcnQgbG9nID0gcmVxdWlyZSgnbG9nbGV2ZWwnKVxuaW1wb3J0ICogYXMgbG9nIGZyb20gJ2xvZ2xldmVsJztcbi8vIGltcG9ydCBsb2cgZnJvbSAnbG9nbGV2ZWwnO1xuaW1wb3J0IHsgRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlL0VuY3J5cHRpb25TZXJ2aWNlXCI7XG5pbXBvcnQgeyBTSkNMRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlL1NKQ0xFbmNyeXB0aW9uU2VydmljZVwiO1xuLy8gdmFyIG1hcmtkb3duaXQgPSByZXF1aXJlKCdtYXJrZG93bi1pdCcpO1xudmFyIG1kID0gbmV3IG1hcmtkb3duaXQoKTtcblxuXG5jb25zdCB1c2VyQm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NvbnRhY3RzLWJveCcpO1xuXG5sb2cuc2V0TGV2ZWwoXCJUUkFDRVwiKVxuXG5jb25zdCBjaGF0TW9kZWwgPSBuZXcgQ2hhdE1vZGVsKCk7XG5cbmNvbnN0IHVzZXJNb2RlbCA9IG5ldyBVc2VyTW9kZWwoKTtcbi8vIGNvbnN0IHVzZXJNb2RlbCA9IE1vZGVsRmFjdG9yeS5jcmVhdGVNb2RlbChcIlVTRVJcIik7XG4vLyBAdHMtaWdub3JlOiBBcmd1bWVudCBvZiB0eXBlICdIVE1MRWxlbWVudCB8IG51bGwnIGlzIG5vdCBhc3NpZ25hYmxlIHRvIHBhcmFtZXRlciBvZiB0eXBlICdIVE1MRWxlbWVudCcuIFR5cGUgJ251bGwnIGlzIG5vdCBhc3NpZ25hYmxlIHRvIHR5cGUgJ0hUTUxFbGVtZW50Jy5cbmNvbnN0IHVzZXJWaWV3ID0gbmV3IFVzZXJWaWV3KHVzZXJNb2RlbCwgY2hhdE1vZGVsLCB1c2VyQm94KTtcblxuLy8gY29uc29sZS5sb2codXNlckJveCk7XG5cbnVzZXJNb2RlbC5hdHRhY2godXNlclZpZXcpO1xuLy8gdXNlclZpZXcubW9kZWxcblxuXG5jb25zdCB1c2VyQ29udHJvbGxlciA9IG5ldyBVc2VyQ29udHJvbGxlcih1c2VyTW9kZWwsIHVzZXJWaWV3KTtcbnVzZXJDb250cm9sbGVyLnRlc3QoKTtcblxuXG5cbi8vIHVzZXJNb2RlbC5zb21lQnVzaW5lc3NNZXRob2QoYWN0aXZlVXNlcnNNb2NrKTtcbmxvZy5pbmZvKFwiaGVsbG9cIik7XG5cbmNvbnN0IGNoYXRBcmVhID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NoYXQtYXJlYS1uZXcnKTtcbi8vIEB0cy1pZ25vcmU6IEFyZ3VtZW50IG9mIHR5cGUgJ0hUTUxFbGVtZW50IHwgbnVsbCcgaXMgbm90IGFzc2lnbmFibGUgdG8gcGFyYW1ldGVyIG9mIHR5cGUgJ0hUTUxFbGVtZW50Jy4gVHlwZSAnbnVsbCcgaXMgbm90IGFzc2lnbmFibGUgdG8gdHlwZSAnSFRNTEVsZW1lbnQnLlxuY29uc3QgY2hhdFZpZXcgPSBuZXcgQ2hhdFZpZXcoY2hhdE1vZGVsLCBjaGF0QXJlYSk7XG5jb25zdCBjaGF0Q29udHJvbGxlciA9IG5ldyBDaGF0Q29udHJvbGxlcihjaGF0TW9kZWwsIGNoYXRWaWV3KTtcblxuXG5mdW5jdGlvbiBzb21lRnVuYyh2bTogQWN0aXZlVXNlclZpZXdNb2RlbCk6IHZvaWQge1xuICAgIC8vIGxvZy5pbmZvKHZtKTtcbiAgICAvLyBsb2dnZXIuaW5mbyh2bSlcbn1cblxubG9nLmluZm8oXCJ0ZXN0XCIpO1xuLy8gc29tZUZ1bmMoYWN0aXZlVXNlclZpZXdNb2RlbE1vY2spO1xuXG4vLyBAdHMtaWdub3JlOiBPYmplY3QgaXMgcG9zc2libHkgJ251bGwnLlxudmFyIHNvdXJjZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibXNnX2NvbnRhaW5lcl90ZW1wbGF0ZVwiKS5pbm5lckhUTUw7XG5cbnZhciBtc2dDb250YWluZXJUZW1wbGF0ZSA9IEhhbmRsZWJhcnMuY29tcGlsZShzb3VyY2UpO1xuXG5Kc29uQVBJLkFDVElWRV9VU0VSU19HRVQgKyAnYWVmJztcblxuY29uc3QgZW5jcnlwdGlvblNlcnZpY2U6IEVuY3J5cHRpb25TZXJ2aWNlID0gbmV3IFNKQ0xFbmNyeXB0aW9uU2VydmljZSgpO1xubGV0IGN0ID0gZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdChcInBhc3N3b3JkXCIsXCJkYXRhXCIpO1xuY29uc29sZS5sb2coZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChcInBhc3N3b3JkXCIsIGN0KSk7XG5cbkhhbmRsZWJhcnMucmVnaXN0ZXJIZWxwZXIoJ2F2YXRhcicsIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAnPGRpdiBjbGFzcz1cImltZ19jb250X21zZ1wiPiA8aW1nIHNyYz1cImh0dHBzOi8vc3RhdGljLnR1cmJvc3F1aWQuY29tL1ByZXZpZXcvMDAxMjkyLzQ4MS9XVi9fRC5qcGdcIiBjbGFzcz1cInJvdW5kZWQtY2lyY2xlIHVzZXJfaW1nX21zZ1wiPiA8L2Rpdj4nO1xufSk7IiwiaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCIuLi9vYnNlcnZlL09ic2VydmFibGVcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIi4vQWJzdHJhY3RNb2RlbFwiO1xuaW1wb3J0IHsgT2JzZXJ2ZXIgfSBmcm9tIFwiLi4vb2JzZXJ2ZS9PYnNlcnZlclwiO1xuaW1wb3J0IHsgZmV0Y2hFcnJvckhhbmRsZXIgfSBmcm9tIFwiLi9GZXRjaEVycm9ySGFuZGxlclwiO1xuaW1wb3J0IHsgQWN0aXZlVXNlclZpZXdNb2RlbCB9IGZyb20gXCIuLi92aWV3bW9kZWwvQWN0aXZlVXNlclZpZXdNb2RlbFwiO1xuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwgfSBmcm9tIFwiLi4vdmlld21vZGVsL0NoYXRNZXNzYWdlVmlld01vZGVsXCI7XG5pbXBvcnQgeyBKc29uQVBJIH0gZnJvbSBcIi4uL3NpbmdsZXRvbi9Kc29uQVBJXCI7XG5pbXBvcnQgbG9nID0gcmVxdWlyZSgnbG9nbGV2ZWwnKTtcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2UvRW5jcnlwdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IFNKQ0xFbmNyeXB0aW9uU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlL1NKQ0xFbmNyeXB0aW9uU2VydmljZVwiO1xuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VEVE8gfSBmcm9tIFwiLi4vZHRvL0NoYXRNZXNzYWdlRFRPXCI7XG5pbXBvcnQgeyBDaGF0TW9kZWxIZWxwZXIgfSBmcm9tIFwiLi9DaGF0TW9kZWxIZWxwZXJcIjtcblxuZXhwb3J0IGNsYXNzIENoYXRNb2RlbCBpbXBsZW1lbnRzIFN1YmplY3Qge1xuICAgIC8qKlxuICAqIEB0eXBlIHtPYnNlcnZlcltdfSBMaXN0IG9mIHN1YnNjcmliZXJzLiBJbiByZWFsIGxpZmUsIHRoZSBsaXN0IG9mXG4gICogc3Vic2NyaWJlcnMgY2FuIGJlIHN0b3JlZCBtb3JlIGNvbXByZWhlbnNpdmVseSAoY2F0ZWdvcml6ZWQgYnkgZXZlbnRcbiAgKiB0eXBlLCBldGMuKS5cbiAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vYnNlcnZlcnM6IE9ic2VydmVyW10gPSBbXTtcbiAgICBwcml2YXRlIHN0YXRlOiBDaGF0TWVzc2FnZVZpZXdNb2RlbFtdIHwgbnVsbDtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlc01hcDogTWFwPHN0cmluZywgQ2hhdE1lc3NhZ2VWaWV3TW9kZWxbXT47XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMuX21lc3NhZ2VzTWFwID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGUgc3Vic2NyaXB0aW9uIG1hbmFnZW1lbnQgbWV0aG9kcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXR0YWNoKG9ic2VydmVyOiBPYnNlcnZlcik6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZygnU3ViamVjdDogQXR0YWNoZWQgYW4gb2JzZXJ2ZXIuJyk7XG4gICAgICAgIHRoaXMuX29ic2VydmVycy5wdXNoKG9ic2VydmVyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGV0YWNoKG9ic2VydmVyOiBPYnNlcnZlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBvYnNlcnZlckluZGV4ID0gdGhpcy5fb2JzZXJ2ZXJzLmluZGV4T2Yob2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLl9vYnNlcnZlcnMuc3BsaWNlKG9ic2VydmVySW5kZXgsIDEpO1xuICAgICAgICBjb25zb2xlLmxvZygnU3ViamVjdDogRGV0YWNoZWQgYW4gb2JzZXJ2ZXIuJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFVzZXJNZXNzYWdlcyh1c2VybmFtZTogc3RyaW5nLCBtZXNzYWdlczogQ2hhdE1lc3NhZ2VWaWV3TW9kZWxbXSkge1xuICAgICAgICB0aGlzLl9tZXNzYWdlc01hcC5zZXQodXNlcm5hbWUsIG1lc3NhZ2VzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIGFuIHVwZGF0ZSBpbiBlYWNoIHN1YnNjcmliZXIuXG4gICAgICovXG4gICAgcHVibGljIG5vdGlmeSgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1N1YmplY3Q6IE5vdGlmeWluZyBvYnNlcnZlcnMuLi4nKTtcbiAgICAgICAgZm9yIChjb25zdCBvYnNlcnZlciBvZiB0aGlzLl9vYnNlcnZlcnMpIHtcbiAgICAgICAgICAgIG9ic2VydmVyLnVwZGF0ZSh0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzb21lQnVzaW5lc3NNZXRob2QoY2hhdE1lc3NhZ2VMaXN0OiBDaGF0TWVzc2FnZVZpZXdNb2RlbFtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBjaGF0TWVzc2FnZUxpc3Q7XG4gICAgICAgIHRoaXMuaGVscGVyTWV0aG9kKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBTdWJqZWN0OiBNeSBzdGF0ZSBoYXMganVzdCBjaGFuZ2VkYCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYXRNZXNzYWdlTGlzdCk7XG4gICAgICAgIHRoaXMubm90aWZ5KCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldG1lc3NhZ2VzKHVzZXJOYW1lOiBzdHJpbmcsIHBhc3NwaHJhc2U6IHN0cmluZywgbGFzdE1lc3NhZ2VUaW1lOiBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNWTXMgPSBDaGF0TW9kZWxIZWxwZXIuZ2V0TWVzc2FnZXModXNlck5hbWUsIHBhc3NwaHJhc2UsIGxhc3RNZXNzYWdlVGltZSwgdGhpcyk7XG4gICAgICAgIGlmIChjVk1zICE9IG51bGwpIHtcbiAgICAgICAgICAgIGxvZy5pbmZvKCdTdWJqZWN0OiBNeSBzdGF0ZSBoYXMganVzdCBjaGFuZ2VkJylcbiAgICAgICAgICAgIGxvZy5kZWJ1ZyhjVk1zKTtcbiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2VzTWFwLnNldCh1c2VyTmFtZSwgY1ZNcyk7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeSgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbG9nLmVycm9yKCdNZXNzYWdlcyB3ZXJlIG51bGwnKTtcbiAgICAgICAgfVxuICAgIH1cblxuXG5cbiAgICBwcml2YXRlIGhlbHBlck1ldGhvZCgpIHsgfVxuXG4gICAgcHVibGljIHBvcHVsYXRlTWVzc2FnZXMoKTogdm9pZCB7XG5cbiAgICB9XG5cblxuXG59IiwiaW1wb3J0IHsgQ2hhdE1lc3NhZ2VEVE8gfSBmcm9tIFwiLi4vZHRvL0NoYXRNZXNzYWdlRFRPXCI7XG5cbmltcG9ydCAqIGFzIGxvZyBmcm9tIFwibG9nbGV2ZWxcIjtcblxuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwgfSBmcm9tIFwiLi4vdmlld21vZGVsL0NoYXRNZXNzYWdlVmlld01vZGVsXCI7XG5cbmltcG9ydCB7IEpzb25BUEkgfSBmcm9tIFwiLi4vc2luZ2xldG9uL0pzb25BUElcIjtcblxuaW1wb3J0IHsgZmV0Y2hFcnJvckhhbmRsZXIgfSBmcm9tIFwiLi9GZXRjaEVycm9ySGFuZGxlclwiO1xuXG5pbXBvcnQgeyBFbmNyeXB0aW9uU2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlL0VuY3J5cHRpb25TZXJ2aWNlXCI7XG5pbXBvcnQgeyBTSkNMRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tIFwiLi4vc2VydmljZS9TSkNMRW5jcnlwdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IENoYXRNb2RlbCB9IGZyb20gXCIuL0NoYXRNb2RlbFwiO1xuXG5leHBvcnQgY2xhc3MgQ2hhdE1vZGVsSGVscGVyIHtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBlbmNyeXB0aW9uU2VydmljZSA9IG5ldyBTSkNMRW5jcnlwdGlvblNlcnZpY2UoKTtcblxuICAgIHB1YmxpYyBzdGF0aWMgZ2V0TWVzc2FnZXModXNlck5hbWU6IHN0cmluZywgcGFzc3BocmFzZTogc3RyaW5nLCBsYXN0TWVzc2FnZVRpbWU6IHN0cmluZyB8IG51bGwsIGNoYXRNb2RlbDogQ2hhdE1vZGVsKTogQ2hhdE1lc3NhZ2VWaWV3TW9kZWxbXSB8IG51bGwge1xuICAgICAgICBzd2l0Y2ggKGxhc3RNZXNzYWdlVGltZSkge1xuICAgICAgICAgICAgY2FzZSBudWxsOiB7XG4gICAgICAgICAgICAgICAgdGhpcy5nZXRBbGxNZXNzYWdlc0FqYXgodXNlck5hbWUpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKChkYXRhOiBDaGF0TWVzc2FnZURUT1tdKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cuZGVidWcoYFN1YmplY3Q6IHJlY2VpdmVkIGFsbCBtZXNzYWdlc2ApO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGV0IHVzZXJOYW1lcyA9IGRhdGEubWFwKENoYXRNZXNzYWdlVmlld01vZGVsID0+IENoYXRNZXNzYWdlVmlld01vZGVsLmZyb21Vc2VyKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGV0IHN1bXQgPSBkYXRhLm1hcChjaGF0TWVzc2FnZVZpZXdNb2RlbCA9PiB7IHJldHVybiB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQocGFzc3BocmFzZSwgY2hhdE1lc3NhZ2VWaWV3TW9kZWwubWVzc2FnZUNpcGhlcikgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YS5tYXAodm0gPT4gdGhpcy50b0NoYXRNZXNzYWdlVk0odm0sIHBhc3NwaHJhc2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoYXRNb2RlbC5zZXRVc2VyTWVzc2FnZXModXNlck5hbWUsIGNoYXRNZXNzYWdlVk1zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoYXRNb2RlbC5ub3RpZnkoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICAgICAgICB0aGlzLmdldE5ld01lc3NhZ2VzQWpheCh1c2VyTmFtZSwgbGFzdE1lc3NhZ2VUaW1lKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoZGF0YTogQ2hhdE1lc3NhZ2VEVE9bXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKGBTdWJqZWN0OiByZWNlaXZlZCBuZXcgbWVzc2FnZXNgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhLm1hcCh2bSA9PiB0aGlzLnRvQ2hhdE1lc3NhZ2VWTSh2bSwgcGFzc3BocmFzZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2hhdE1vZGVsLnNldFVzZXJNZXNzYWdlcyh1c2VyTmFtZSwgY2hhdE1lc3NhZ2VWTXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcy5zdGF0ZSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGF0TW9kZWwubm90aWZ5KCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyB0b0NoYXRNZXNzYWdlVk0oY2hhdE1lc3NhZ2VEVE86IENoYXRNZXNzYWdlRFRPLCBwYXNzcGhyYXNlOiBzdHJpbmcpOiBDaGF0TWVzc2FnZVZpZXdNb2RlbCB7XG4gICAgICAgIGNvbnN0IHZtID0gbmV3IENoYXRNZXNzYWdlVmlld01vZGVsKCk7XG4gICAgICAgIHZtLmZyb21Vc2VyID0gY2hhdE1lc3NhZ2VEVE8uZnJvbVVzZXI7XG4gICAgICAgIHZtLnRvVXNlciA9IGNoYXRNZXNzYWdlRFRPLnRvVXNlcjtcbiAgICAgICAgdm0ubWVzc2FnZVRpbWUgPSBjaGF0TWVzc2FnZURUTy5tZXNzYWdlVGltZTtcbiAgICAgICAgdm0ubWVzc2FnZSA9IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZGVjcnlwdChwYXNzcGhyYXNlLCBjaGF0TWVzc2FnZURUTy5tZXNzYWdlQ2lwaGVyKSBhcyBzdHJpbmc7XG4gICAgICAgIHJldHVybiB2bTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBhc3luYyBnZXRBbGxNZXNzYWdlc0FqYXgodG9Vc2VyOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICAgICAgICBsZXQgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gICAgICAgIGlmIChKc29uQVBJLmF1dGhUb2tlbiA9PSBudWxsKSB7XG4gICAgICAgICAgICBsb2cuZXJyb3IoXCJhdXRoVG9rZW4gbnVsbFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfTtcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoJ1gtQVVUSC1UT0tFTicsIEpzb25BUEkuYXV0aFRva2VuKTtcbiAgICAgICAgbGV0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7SnNvbkFQSS5DSEFUX01FU1NBR0VTX0dFVH0vJHt0b1VzZXJ9YCwge1xuICAgICAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgICAgIGhlYWRlcnM6IGhlYWRlcnNcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlLmNsb25lKCkpO1xuICAgICAgICBpZiAoZmV0Y2hFcnJvckhhbmRsZXIocmVzcG9uc2UuY2xvbmUoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGxldCBkYXRhOiBQcm9taXNlPGFueT4gPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGFzeW5jIGdldE5ld01lc3NhZ2VzQWpheCh0b1VzZXI6IHN0cmluZywgbGFzdE1lc3NhZ2VUaW1lU3RhbXA6IHN0cmluZyk6IFByb21pc2U8YW55PiB7XG4gICAgICAgIGxldCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcbiAgICAgICAgaWYgKEpzb25BUEkuYXV0aFRva2VuID09IG51bGwpIHtcbiAgICAgICAgICAgIGxvZy5lcnJvcihcImF1dGhUb2tlbiBudWxsXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9O1xuICAgICAgICBoZWFkZXJzLmFwcGVuZCgnWC1BVVRILVRPS0VOJywgSnNvbkFQSS5hdXRoVG9rZW4pO1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgJHtKc29uQVBJLkNIQVRfTUVTU0FHRVNfR0VUfS8ke3RvVXNlcn0vJHtsYXN0TWVzc2FnZVRpbWVTdGFtcH1gLCB7XG4gICAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgICAgaGVhZGVyczogaGVhZGVyc1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UuY2xvbmUoKSk7XG4gICAgICAgIGlmIChmZXRjaEVycm9ySGFuZGxlcihyZXNwb25zZS5jbG9uZSgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGRhdGE6IFByb21pc2U8YW55PiA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxufSIsImV4cG9ydCBmdW5jdGlvbiBmZXRjaEVycm9ySGFuZGxlcihyZXNwb25zZTogUmVzcG9uc2UpIHtcbiAgICAvLyBhbGVydGlmeS5zdWNjZXNzKCdDdXJyZW50IHBvc2l0aW9uIDogJyArIGFsZXJ0aWZ5LmdldCgnbm90aWZpZXInLCAncG9zaXRpb24nKSk7XG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAvLyB0aGUgc3RhdHVzIHdhcyBub3Qgb2sgYW5kIHRoZXJlIGlzIG5vIGpzb24gYm9keVxuICAgICAgICAgICAgLy8gdGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpO1xuICAgICAgICAgICAgLy8gd2luZG93LmFsZXJ0KHNwcmludGYoJ1NvbWUgZXJyb3Igb2NjdXJlZC4gSHR0cCBjb2RlIGlzICVzJywgcmVzcG9uc2Uuc3RhdHVzKSk7XG4gICAgICAgICAgICAvLyBhbGVydGlmeS5lcnJvcihzcHJpbnRmKCdTb21lIGVycm9yIG9jY3VyZWQuIEh0dHAgY29kZSBpcyAlcycsIHJlc3BvbnNlLnN0YXR1cykpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pLnRoZW4oanNvbiA9PiB7XG4gICAgICAgICAgICAvLyB0aGUgc3RhdHVzIHdhcyBub3Qgb2sgYnV0IHRoZXJlIGlzIGEganNvbiBib2R5XG4gICAgICAgICAgICAvLyB0aHJvdyBuZXcgRXJyb3IoanNvbi5lcnJvci5tZXNzYWdlKTsgLy8gZXhhbXBsZSBlcnJvciBtZXNzYWdlIHJldHVybmVkIGJ5IGEgUkVTVCBBUElcbiAgICAgICAgICAgIC8vIHdpbmRvdy5hbGVydChzcHJpbnRmKCdFcnJvcjogJXMgKEh0dHAgY29kZSAlcyknLCBqc29uLCByZXNwb25zZS5zdGF0dXMpKTtcbiAgICAgICAgICAgIC8vIGFsZXJ0aWZ5LmVycm9yKHNwcmludGYoJ1NvbWUgZXJyb3Igb2NjdXJlZC4gSHR0cCBjb2RlIGlzICVzJywgcmVzcG9uc2Uuc3RhdHVzKSk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhqc29uKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9XG59IiwiaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCIuLi9vYnNlcnZlL09ic2VydmFibGVcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIi4vQWJzdHJhY3RNb2RlbFwiO1xuaW1wb3J0IHsgT2JzZXJ2ZXIgfSBmcm9tIFwiLi4vb2JzZXJ2ZS9PYnNlcnZlclwiO1xuaW1wb3J0IHsgZmV0Y2hFcnJvckhhbmRsZXIgfSBmcm9tIFwiLi9GZXRjaEVycm9ySGFuZGxlclwiO1xuaW1wb3J0IHsgQWN0aXZlVXNlclZpZXdNb2RlbCB9IGZyb20gXCIuLi92aWV3bW9kZWwvQWN0aXZlVXNlclZpZXdNb2RlbFwiO1xuaW1wb3J0IHsgSnNvbkFQSSB9IGZyb20gXCIuLi9zaW5nbGV0b24vSnNvbkFQSVwiO1xuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwgfSBmcm9tIFwiLi4vdmlld21vZGVsL0NoYXRNZXNzYWdlVmlld01vZGVsXCI7XG5cbmV4cG9ydCBjbGFzcyBVc2VyTW9kZWwgaW1wbGVtZW50cyBTdWJqZWN0IHtcbiAgICAvKipcbiAgKiBAdHlwZSB7T2JzZXJ2ZXJbXX0gTGlzdCBvZiBzdWJzY3JpYmVycy4gSW4gcmVhbCBsaWZlLCB0aGUgbGlzdCBvZlxuICAqIHN1YnNjcmliZXJzIGNhbiBiZSBzdG9yZWQgbW9yZSBjb21wcmVoZW5zaXZlbHkgKGNhdGVnb3JpemVkIGJ5IGV2ZW50XG4gICogdHlwZSwgZXRjLikuXG4gICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBvYnNlcnZlcnM6IE9ic2VydmVyW10gPSBbXTtcbiAgICBwcml2YXRlIHN0YXRlOiBBY3RpdmVVc2VyVmlld01vZGVsW10gfCB1bmRlZmluZWQ7XG4gICAgLy8gQHRzLWlnbm9yZTogQ2Fubm90IGZpbmQgbmFtZSAnaG9zdEFkZHJlc3MnLlxuXG4gICAgY29uc3RydWN0b3IoKSB7IH1cbiAgICAvKipcbiAgICAgKiBUaGUgc3Vic2NyaXB0aW9uIG1hbmFnZW1lbnQgbWV0aG9kcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXR0YWNoKG9ic2VydmVyOiBPYnNlcnZlcik6IHZvaWQge1xuICAgICAgICBjb25zb2xlLmxvZygnU3ViamVjdDogQXR0YWNoZWQgYW4gb2JzZXJ2ZXIuJyk7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXJzLnB1c2gob2JzZXJ2ZXIpO1xuICAgIH1cblxuICAgIHB1YmxpYyBkZXRhY2gob2JzZXJ2ZXI6IE9ic2VydmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG9ic2VydmVySW5kZXggPSB0aGlzLm9ic2VydmVycy5pbmRleE9mKG9ic2VydmVyKTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnMuc3BsaWNlKG9ic2VydmVySW5kZXgsIDEpO1xuICAgICAgICBjb25zb2xlLmxvZygnU3ViamVjdDogRGV0YWNoZWQgYW4gb2JzZXJ2ZXIuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlciBhbiB1cGRhdGUgaW4gZWFjaCBzdWJzY3JpYmVyLlxuICAgICAqL1xuICAgIHB1YmxpYyBub3RpZnkoKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdTdWJqZWN0OiBOb3RpZnlpbmcgb2JzZXJ2ZXJzLi4uJyk7XG4gICAgICAgIGZvciAoY29uc3Qgb2JzZXJ2ZXIgb2YgdGhpcy5vYnNlcnZlcnMpIHtcbiAgICAgICAgICAgIG9ic2VydmVyLnVwZGF0ZSh0aGlzLnN0YXRlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzb21lQnVzaW5lc3NNZXRob2QoYWN0aXZldXNlckxpc3Q6IEFjdGl2ZVVzZXJWaWV3TW9kZWxbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLnN0YXRlID0gYWN0aXZldXNlckxpc3Q7XG4gICAgICAgIHRoaXMuaGVscGVyTWV0aG9kKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBTdWJqZWN0OiBNeSBzdGF0ZSBoYXMganVzdCBjaGFuZ2VkYCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGFjdGl2ZXVzZXJMaXN0KTtcbiAgICAgICAgdGhpcy5ub3RpZnkoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnZXRBY3RpdmVVc2Vyc1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRBY3RpdmVVc2VycygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRBY3RpdmVVc2Vyc0FqYXgoXCJcIiwgSnNvbkFQSS5BQ1RJVkVfVVNFUlNfR0VUKVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gLy8gYWN0aXZlVXNlcnMgPSBkYXRhO1xuICAgICAgICAgICAgICAgIC8vIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0oJ2FjdGl2ZVVzZXJzJywgSlNPTi5zdHJpbmdpZnkoZGF0YSkpO1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oJ2FjdGl2ZVVzZXJzJykpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBTdWJqZWN0OiByZWNlaXZlZCBhamF4IGFjdGl2ZSB1c2Vyc2ApO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUgPSBkYXRhO1xuICAgICAgICAgICAgICAgIHRoaXMubm90aWZ5KCk7XG4gICAgICAgICAgICB9KVxuICAgIH1cblxuICAgIGFzeW5jIGdldEFjdGl2ZVVzZXJzQWpheChhdXRoVG9rZW4yOiBzdHJpbmcsIFVSTDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgbGV0IGhlYWRlcnMgPSBuZXcgSGVhZGVycygpO1xuICAgICAgICAvLyBoZWFkZXJzLmFwcGVuZCgnQXV0aG9yaXphdGlvbicsIGJhc2ljQXV0aFRva2VuKTtcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoJ1gtQVVUSC1UT0tFTicsIGF1dGhUb2tlbjIpO1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChKc29uQVBJLkFDVElWRV9VU0VSU19HRVQsIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgICAgICBoZWFkZXJzOiBoZWFkZXJzXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZS5jbG9uZSgpKTtcbiAgICAgICAgaWYgKGZldGNoRXJyb3JIYW5kbGVyKHJlc3BvbnNlLmNsb25lKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgLy8gcmV0dXJuIGRhdGE7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAoZGF0YSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YSlcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICByZWplY3QoJ1Jlc3BvbnNlIGRhdGEgbnVsbCcpXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoZWxwZXJNZXRob2QoKSB7IH1cblxufSIsImltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vRW5jcnlwdGlvblNlcnZpY2VcIjtcbmltcG9ydCAqIGFzIHNqY2wgZnJvbSBcInNqY2xcIjtcblxuZXhwb3J0IGNsYXNzIFNKQ0xFbmNyeXB0aW9uU2VydmljZSBpbXBsZW1lbnRzIEVuY3J5cHRpb25TZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBhcmFtczogYW55ID0geyBtb2RlOiBcImdjbVwiLCB0czogMTI4LCBhZGF0YTogXCJcIiwgaXRlcjogMTAwMDB9XG4gICAgcHVibGljIGVuY3J5cHQocGFzc3BocmFzZTogc3RyaW5nLCBwbGFpblRleHQ6IHN0cmluZyk6IE9iamVjdCB7XG4gICAgICAgIHJldHVybiBzamNsLmVuY3J5cHQocGFzc3BocmFzZSwgcGxhaW5UZXh0LCB0aGlzLnBhcmFtcyk7XG4gICAgfSBcbiAgICBcbiAgICBwdWJsaWMgZGVjcnlwdChwYXNzcGhyYXNlOiBzdHJpbmcsIGNpcGhlcjogT2JqZWN0KTogT2JqZWN0IHtcbiAgICAgICAgcmV0dXJuIHNqY2wuZGVjcnlwdChwYXNzcGhyYXNlLCBjaXBoZXIgYXMgc2pjbC5TamNsQ2lwaGVyRW5jcnlwdGVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gICAgfVxufSIsImV4cG9ydCBuYW1lc3BhY2UgSnNvbkFQSSB7XG4gICAgLy8gQHRzLWlnbm9yZTogQ2Fubm90IGZpbmQgbmFtZSAnaG9zdEFkZHJlc3MnLlxuICAgIGV4cG9ydCBsZXQgdXNlck5hbWU6IHN0cmluZyB8IG51bGwgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgndXNlck5hbWUnKTtcbiAgICBleHBvcnQgbGV0IGF1dGhUb2tlbjogc3RyaW5nIHwgbnVsbCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdhdXRoVG9rZW4nKTtcbiAgICBleHBvcnQgY29uc3QgQUNUSVZFX1VTRVJTX0dFVCA9IGAvYXBpL2NoYXQvZ2V0L2FjdGl2ZS11c2Vyc2A7XG4gICAgZXhwb3J0IGNvbnN0IENIQVRfTUVTU0FHRVNfR0VUID0gYGA7XG4gICAgXG59IiwiZXhwb3J0IGNsYXNzIFRlbXBsYXRlRmFjdG9yeSB7XG4gICAgLy8gc3RhdGljIGdldFRlbXBsYXRlKHRlbXBsYXRlTmFtZTogc3RyaW5nKTogSGFuZGxlYmFycy5UZW1wbGF0ZURlbGVnYXRlPGFueT4ge1xuXG4gICAgLy8gICAgIHN3aXRjaCAodGVtcGxhdGVOYW1lKSB7XG4gICAgLy8gICAgICAgICBjYXNlIFwidXNlci1jb250YWN0LW9ubGluZS10ZW1wbGF0ZVwiOiB7XG4gICAgLy8gICAgICAgICAgICAgLy8gbGV0IHNvdXJjZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwidXNlci1jb250YWN0LW9ubGluZS10ZW1wbGF0ZVwiKS5pbm5lckhUTUw7XG4gICAgLy8gICAgICAgICAgICAgLy8gbGV0IG1zZ0NvbnRhaW5lclRlbXBsYXRlID0gSGFuZGxlYmFycy5jb21waWxlKHNvdXJjZSk7XG4gICAgLy8gICAgICAgICAgICAgLy8gcmV0dXJuIG1zZ0NvbnRhaW5lclRlbXBsYXRlO1xuICAgIC8vICAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVRlbXBsYXRlKHRlbXBsYXRlTmFtZSk7XG4gICAgLy8gICAgICAgICB9XG4gICAgLy8gICAgICAgICBjYXNlIFwibXNnX2NvbnRhaW5lcl9zZW5kX3RlbXBsYXRlXCI6IHtcbiAgICAvLyAgICAgICAgICAgICAvLyBsZXQgc291cmNlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJtc2dfY29udGFpbmVyX3NlbmRfdGVtcGxhdGVcIikuaW5uZXJIVE1MO1xuICAgIC8vICAgICAgICAgICAgIC8vIGxldCBtc2dDb250YWluZXJUZW1wbGF0ZSA9IEhhbmRsZWJhcnMuY29tcGlsZShzb3VyY2UpO1xuICAgIC8vICAgICAgICAgICAgIC8vIHJldHVybiBtc2dDb250YWluZXJUZW1wbGF0ZTtcbiAgICAvLyAgICAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVUZW1wbGF0ZSh0ZW1wbGF0ZU5hbWUpO1xuICAgIC8vICAgICAgICAgfVxuICAgIC8vICAgICAgICAgY2FzZSBcIm1zZ19jb250YWluZXJfdGVtcGxhdGVcIjoge1xuICAgIC8vICAgICAgICAgICAgIC8vIGxldCBzb3VyY2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcIm1zZ19jb250YWluZXJfc2VuZF90ZW1wbGF0ZVwiKS5pbm5lckhUTUw7XG4gICAgLy8gICAgICAgICAgICAgLy8gbGV0IG1zZ0NvbnRhaW5lclRlbXBsYXRlID0gSGFuZGxlYmFycy5jb21waWxlKHNvdXJjZSk7XG4gICAgLy8gICAgICAgICAgICAgLy8gcmV0dXJuIG1zZ0NvbnRhaW5lclRlbXBsYXRlO1xuICAgIC8vICAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVRlbXBsYXRlKHRlbXBsYXRlTmFtZSk7XG4gICAgLy8gICAgICAgICB9XG4gICAgLy8gICAgICAgICBkZWZhdWx0OlxuICAgIC8vICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCB0ZW1wbGF0ZSBuYW1lJyk7XG4gICAgLy8gICAgIH1cbiAgICAvLyB9XG5cbiAgICBzdGF0aWMgZ2V0VGVtcGxhdGUodGVtcGxhdGVOYW1lOiBzdHJpbmcpOiBIYW5kbGViYXJzLlRlbXBsYXRlRGVsZWdhdGU8YW55PiB7XG4gICAgICAgIC8vQHRzLWlnbm9yZTogT2JqZWN0IGlzIHBvc3NpYmx5ICdudWxsJy5cbiAgICAgICAgbGV0IHNvdXJjZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRlbXBsYXRlTmFtZSkuaW5uZXJIVE1MO1xuICAgICAgICBsZXQgbXNnQ29udGFpbmVyVGVtcGxhdGUgPSBIYW5kbGViYXJzLmNvbXBpbGUoc291cmNlKTtcbiAgICAgICAgcmV0dXJuIG1zZ0NvbnRhaW5lclRlbXBsYXRlO1xuICAgIH1cbn0iLCJpbXBvcnQgeyBPYnNlcnZlciB9IGZyb20gXCIuLi9vYnNlcnZlL09ic2VydmVyXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9BYnN0cmFjdE1vZGVsXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcIi4uL29ic2VydmUvT2JzZXJ2YWJsZVwiO1xuaW1wb3J0IHsgVmlldyB9IGZyb20gXCIuL0Fic3RyYWN0Vmlld1wiO1xuaW1wb3J0IHsgQ29udHJvbGxlciB9IGZyb20gXCIuLi9jb250cm9sbGVyL0Fic3RyYWN0Q29udHJvbGxlclwiO1xuaW1wb3J0IHsgVGVtcGxhdGVGYWN0b3J5IH0gZnJvbSBcIi4uL3RlbXBsYXRlL1RlbXBsYXRlRmFjdG9yeVwiO1xuaW1wb3J0IHsgQWN0aXZlVXNlclZpZXdNb2RlbCB9IGZyb20gXCIuLi92aWV3bW9kZWwvQWN0aXZlVXNlclZpZXdNb2RlbFwiO1xuaW1wb3J0IHsgQ2hhdE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0NoYXRNb2RlbFwiO1xuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwgfSBmcm9tIFwiLi4vdmlld21vZGVsL0NoYXRNZXNzYWdlVmlld01vZGVsXCI7XG5pbXBvcnQgKiBhcyBsb2cgZnJvbSAnbG9nbGV2ZWwnO1xuXG5leHBvcnQgY2xhc3MgQ2hhdFZpZXcgaW1wbGVtZW50cyBPYnNlcnZlciB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfbW9kZWw6IENoYXRNb2RlbDtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlU2VuZFRlbXBsYXRlID0gVGVtcGxhdGVGYWN0b3J5LmdldFRlbXBsYXRlKCdtc2dfY29udGFpbmVyX3NlbmRfdGVtcGxhdGUnKTtcblxuXG4gICAgY29uc3RydWN0b3IobW9kZWw6IENoYXRNb2RlbCwgZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fbW9kZWwgPSBtb2RlbDtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG5cbiAgICB1cGRhdGUoZGF0YTogQ2hhdE1lc3NhZ2VWaWV3TW9kZWxbXSk6IHZvaWQge1xuICAgICAgICBsZXQgaHRtbDogc3RyaW5nID0gXCJcIjtcbiAgICAgICAgZGF0YS5mb3JFYWNoKCh2bTogQ2hhdE1lc3NhZ2VWaWV3TW9kZWwpID0+IHtcbiAgICAgICAgICAgIGh0bWwgKz0gdGhpcy5fbWVzc2FnZVNlbmRUZW1wbGF0ZSh2bSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9lbGVtZW50LmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIGxvZy5kZWJ1Zyh0aGlzLl9lbGVtZW50LmlubmVySFRNTCk7XG4gICAgfVxufSIsImltcG9ydCB7IE9ic2VydmVyIH0gZnJvbSBcIi4uL29ic2VydmUvT2JzZXJ2ZXJcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Fic3RyYWN0TW9kZWxcIjtcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tIFwiLi4vb2JzZXJ2ZS9PYnNlcnZhYmxlXCI7XG5pbXBvcnQgeyBWaWV3IH0gZnJvbSBcIi4vQWJzdHJhY3RWaWV3XCI7XG5pbXBvcnQgeyBDb250cm9sbGVyIH0gZnJvbSBcIi4uL2NvbnRyb2xsZXIvQWJzdHJhY3RDb250cm9sbGVyXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZUZhY3RvcnkgfSBmcm9tIFwiLi4vdGVtcGxhdGUvVGVtcGxhdGVGYWN0b3J5XCI7XG5pbXBvcnQgeyBBY3RpdmVVc2VyVmlld01vZGVsIH0gZnJvbSBcIi4uL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsXCI7XG5pbXBvcnQgeyBDaGF0TW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQ2hhdE1vZGVsXCI7XG5pbXBvcnQgbG9nID0gcmVxdWlyZShcImxvZ2xldmVsXCIpO1xuXG5leHBvcnQgY2xhc3MgVXNlclZpZXcgaW1wbGVtZW50cyBPYnNlcnZlciB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfbW9kZWw6IE1vZGVsO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NoYXRNb2RlbDogQ2hhdE1vZGVsO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2VsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIC8vIHByaXZhdGUgdXNlckJveGVzOiBhbnlbXSA9ICBbXTtcblxuXG4gICAgY29uc3RydWN0b3IobW9kZWw6IE1vZGVsLCBjaGF0TW9kZWw6IENoYXRNb2RlbCwgZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fbW9kZWwgPSBtb2RlbDtcbiAgICAgICAgdGhpcy5fY2hhdE1vZGVsID0gY2hhdE1vZGVsO1xuICAgICAgICB0aGlzLl9lbGVtZW50ID0gZWxlbWVudDtcbiAgICB9XG5cblxuXG5cbiAgICB1cGRhdGUoZGF0YTogQWN0aXZlVXNlclZpZXdNb2RlbFtdKTogdm9pZCB7XG4gICAgICAgIGxldCB0ZW1wbGF0ZSA9IFRlbXBsYXRlRmFjdG9yeS5nZXRUZW1wbGF0ZSgndXNlci1jb250YWN0LW9ubGluZS10ZW1wbGF0ZScpO1xuICAgICAgICBsZXQgaHRtbDogc3RyaW5nID0gXCJcIjtcbiAgICAgICAgZGF0YS5mb3JFYWNoKChlbGVtZW50OiBBY3RpdmVVc2VyVmlld01vZGVsKSA9PiB7XG4gICAgICAgICAgICBodG1sICs9IHRlbXBsYXRlKGVsZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5pbm5lckhUTUwgPSBodG1sO1xuICAgICAgICB0aGlzLmFkZFVzZXJDYWxsQmFja3MoKTtcbiAgICAgICAgY29uc29sZS5sb2codGhpcy5fZWxlbWVudC5pbm5lckhUTUwpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGVscGVyKCk6IHZvaWQge1xuXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRVc2VyQ2FsbEJhY2tzKCk6IHZvaWQge1xuICAgICAgICBsZXQgdXNlckJveGVzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndXNlci1ib3gnKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB1c2VyQm94ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCB1c2VyQm94ID0gdXNlckJveGVzW2ldO1xuICAgICAgICAgICAgdXNlckJveGVzW2ldLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy51c2VyQ2FsbEJhY2suYmluZCh0aGlzLCB1c2VyQm94KSk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIHByaXZhdGUgdXNlckNhbGxCYWNrKGVsOiBFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGxldCBjdXJyZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndXNlci1ib3ggYWN0aXZlJyk7XG5cbiAgICAgICAgbGV0IHBhc3NwaHJhc2U6IHN0cmluZyA9ICcnO1xuICAgICAgICBpZiAoY3VycmVudC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsZXQgcGFzc3BocmFzZUlucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Bhc3NwaHJhc2UnKSBhcyBhbnk7XG5cbiAgICAgICAgICAgIGlmIChwYXNzcGhyYXNlSW5wdXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGxvZy5lcnJvcigncGFzc3BocmFzZUlucHV0IGVsZW1lbnQgcmVmZXJlbmNlIGlzIG51bGwnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXNzcGhyYXNlID0gcGFzc3BocmFzZUlucHV0LnZhbHVlXG4gICAgICAgICAgICBpZiAocGFzc3BocmFzZSA9PSAnJyB8fCBwYXNzcGhyYXNlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBhbGVydCgnUGxlYXNlIGlucHV0IHBhc3NwaHJhc2UnKVxuICAgICAgICAgICAgICAgIC8vIGFsZXJ0aWZ5LmVycm9yKCdQbGVhc2UgZW50ZXIgYSBwYXNzcGhyYXNlJyk7XG4gICAgICAgICAgICAgICAgbG9nLmVycm9yKCdwYXNzcGhyYXNlIGlzIGVtcHR5IG9yIG51bGwnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50WzBdLmNsYXNzTmFtZSA9IGN1cnJlbnRbMF0uY2xhc3NOYW1lLnJlcGxhY2UoXCIgYWN0aXZlXCIsIFwiXCIpO1xuXG4gICAgICAgIH1cbiAgICAgICAgLy8gQWRkIHRoZSBhY3RpdmUgY2xhc3MgdG8gdGhlIGN1cnJlbnQvY2xpY2tlZCBidXR0b25cbiAgICAgICAgZWxzZSBpZiAoY3VycmVudC5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgbGV0IGVsZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncGFzc3BocmFzZS1pbml0aWFsJykgYXMgYW55O1xuICAgICAgICAgICAgaWYoZWxlbSA9PSBudWxsKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxvZy5lcnJvcigncGFzc3BocmFzZUlucHV0IGVsZW1lbnQgcmVmZXJlbmNlIGlzIG51bGwnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXNzcGhyYXNlID0gZWxlbS52YWx1ZTtcbiAgICAgICAgICAgIGlmIChwYXNzcGhyYXNlID09ICcnIHx8IHBhc3NwaHJhc2UgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vICAgICAvLyBhbGVydCgnUGxlYXNlIGlucHV0IHBhc3NwaHJhc2UnKVxuICAgICAgICAgICAgICAgIC8vICAgICAvLyBhbGVydGlmeS5lcnJvcignUGxlYXNlIGVudGVyIGEgcGFzc3BocmFzZScpO1xuICAgICAgICAgICAgICAgIGxvZy5lcnJvcigncGFzc3BocmFzZSBpcyBlbXB0eSBvciBudWxsJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZTogT2JqZWN0IGlzIHBvc3NpYmx5ICdudWxsJy5cbiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCduby11c2VyLXNlbGVjdGVkJykuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmU6IE9iamVjdCBpcyBwb3NzaWJseSAnbnVsbCcuXG4gICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2hhdC1jYXJkJykuaGlkZGVuID0gZmFsc2U7XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlOiBPYmplY3QgaXMgcG9zc2libHkgJ251bGwnLlxuICAgICAgICAgICAgZWxlbS5oaWRkZW4gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndG8tdXNlci1zcGFuJykpO1xuICAgICAgICBsZXQgZWxlbSA9IGVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3RvLXVzZXItc3BhbicpWzBdIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBsZXQgdXNlck5hbWUgPSBlbGVtLmlubmVyVGV4dDtcbiAgICAgICAgLy8gQHRzLWlnbm9yZTogT2JqZWN0IGlzIHBvc3NpYmx5ICdudWxsJy5cbiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VzZXItbmFtZS1zcGFuJykuaW5uZXJUZXh0ID0gdXNlck5hbWU7XG4gICAgICAgIHRoaXMuX2NoYXRNb2RlbC5nZXRtZXNzYWdlcyh1c2VyTmFtZSwgcGFzc3BocmFzZSwgbnVsbCk7XG4gICAgICAgIC8vIHBvcHVsYXRlTWVzc2FnZXModXNlck5hbWUsIHBhc3NwaHJhc2UpO1xuICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKCdzZWxlY3RlZFVzZXInLCB1c2VyTmFtZSk7XG4gICAgICAgIGVsLmNsYXNzTmFtZSArPSBcIiBhY3RpdmVcIjtcbiAgICB9XG5cbn0iLCJleHBvcnQgY2xhc3MgQWN0aXZlVXNlclZpZXdNb2RlbCB7XG4gICAgdXNlck5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBvbmxpbmU6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gICAgbGFzdEFjdGl2ZTogc3RyaW5nfCB1bmRlZmluZWQ7XG59IiwiZXhwb3J0IGNsYXNzIENoYXRNZXNzYWdlVmlld01vZGVsIHtcbiAgICBwdWJsaWMgdG9Vc2VyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgcHVibGljIGZyb21Vc2VyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgcHVibGljIG1lc3NhZ2UhOiBzdHJpbmc7XG4gICAgcHVibGljIG1lc3NhZ2VUaW1lITogRGF0ZTtcblxuICAgIFxufSJdfQ==