ng2-webstorage
Version:
Angular webstorage manager
446 lines (429 loc) • 63.8 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) :
typeof define === 'function' && define.amd ? define(['exports', '@angular/core'], factory) :
(factory((global.ng2Webstorage = global.ng2Webstorage || {}),global.ng.core));
}(this, (function (exports,_angular_core) { 'use strict';
var STORAGE;
(function (STORAGE) {
STORAGE[STORAGE["local"] = 0] = "local";
STORAGE[STORAGE["session"] = 1] = "session";
})(STORAGE || (STORAGE = {}));
var LIB_KEY = 'ng2-webstorage';
var LIB_KEY_SEPARATOR = '|';
var LIB_KEY_CASE_SENSITIVE = false;
var STORAGE_NAMES = (_a = {},
_a[STORAGE.local] = 'local',
_a[STORAGE.session] = 'session',
_a);
var _a;
var CUSTOM_LIB_KEY = LIB_KEY;
var CUSTOM_LIB_KEY_SEPARATOR = LIB_KEY_SEPARATOR;
var CUSTOM_LIB_KEY_CASE_SENSITIVE = LIB_KEY_CASE_SENSITIVE;
function isManagedKey(sKey) {
return sKey.indexOf(CUSTOM_LIB_KEY + CUSTOM_LIB_KEY_SEPARATOR) === 0;
}
var KeyStorageHelper = (function () {
function KeyStorageHelper() {
}
KeyStorageHelper.isManagedKey = function (sKey) {
return sKey.indexOf(CUSTOM_LIB_KEY + CUSTOM_LIB_KEY_SEPARATOR) === 0;
};
KeyStorageHelper.retrieveKeysFromStorage = function (storage) {
return Object.keys(storage).filter(isManagedKey);
};
KeyStorageHelper.genKey = function (raw) {
if (typeof raw !== 'string')
throw Error('attempt to generate a storage key with a non string value');
return "" + CUSTOM_LIB_KEY + CUSTOM_LIB_KEY_SEPARATOR + this.formatKey(raw);
};
KeyStorageHelper.formatKey = function (raw) {
var key = raw.toString();
return CUSTOM_LIB_KEY_CASE_SENSITIVE ? key : key.toLowerCase();
};
KeyStorageHelper.setStorageKeyPrefix = function (key) {
if (key === void 0) { key = LIB_KEY; }
CUSTOM_LIB_KEY = key;
};
KeyStorageHelper.setCaseSensitivity = function (enable) {
if (enable === void 0) { enable = LIB_KEY_CASE_SENSITIVE; }
CUSTOM_LIB_KEY_CASE_SENSITIVE = enable;
};
KeyStorageHelper.setStorageKeySeparator = function (separator) {
if (separator === void 0) { separator = LIB_KEY_SEPARATOR; }
CUSTOM_LIB_KEY_SEPARATOR = separator;
};
return KeyStorageHelper;
}());
var StorageObserverHelper = (function () {
function StorageObserverHelper() {
}
StorageObserverHelper.observe = function (sType, sKey) {
var oKey = this.genObserverKey(sType, sKey);
if (oKey in this.observers)
return this.observers[oKey];
return this.observers[oKey] = new _angular_core.EventEmitter();
};
StorageObserverHelper.emit = function (sType, sKey, value) {
var oKey = this.genObserverKey(sType, sKey);
if (oKey in this.observers)
this.observers[oKey].emit(value);
};
StorageObserverHelper.genObserverKey = function (sType, sKey) {
return sType + '|' + sKey;
};
StorageObserverHelper.initStorage = function () {
StorageObserverHelper.storageInitStream.emit(true);
};
StorageObserverHelper.observers = {};
StorageObserverHelper.storageInitStream = new _angular_core.EventEmitter();
StorageObserverHelper.storageInit$ = StorageObserverHelper.storageInitStream.asObservable();
return StorageObserverHelper;
}());
var MockStorageHelper = (function () {
function MockStorageHelper() {
}
MockStorageHelper.isSecuredField = function (field) {
return !!~MockStorageHelper.securedFields.indexOf(field);
};
MockStorageHelper.getStorage = function (sType) {
if (!this.mockStorages[sType])
this.mockStorages[sType] = MockStorageHelper.generateStorage();
return this.mockStorages[sType];
};
MockStorageHelper.generateStorage = function () {
var storage = {};
Object.defineProperties(storage, {
setItem: {
writable: false,
enumerable: false,
configurable: false,
value: function (key, value) {
if (!MockStorageHelper.isSecuredField(key))
this[key] = value;
},
},
getItem: {
writable: false,
enumerable: false,
configurable: false,
value: function (key) {
return !MockStorageHelper.isSecuredField(key) ? this[key] || null : null;
},
},
removeItem: {
writable: false,
enumerable: false,
configurable: false,
value: function (key) {
if (!MockStorageHelper.isSecuredField(key))
delete this[key];
},
},
length: {
enumerable: false,
configurable: false,
get: function () {
return Object.keys(this).length;
}
}
});
return storage;
};
MockStorageHelper.securedFields = ['setItem', 'getItem', 'removeItem', 'length'];
MockStorageHelper.mockStorages = {};
return MockStorageHelper;
}());
var CACHED = (_a$1 = {}, _a$1[STORAGE.local] = {}, _a$1[STORAGE.session] = {}, _a$1);
var STORAGEAVAILABILITY = (_b = {}, _b[STORAGE.local] = null, _b[STORAGE.session] = null, _b);
var WebStorageHelper = (function () {
function WebStorageHelper() {
}
WebStorageHelper.store = function (sType, sKey, value) {
this.getStorage(sType).setItem(sKey, JSON.stringify(value));
CACHED[sType][sKey] = value;
StorageObserverHelper.emit(sType, sKey, value);
};
WebStorageHelper.retrieve = function (sType, sKey) {
if (CACHED[sType][sKey])
return CACHED[sType][sKey];
return CACHED[sType][sKey] = WebStorageHelper.retrieveFromStorage(sType, sKey);
};
WebStorageHelper.retrieveFromStorage = function (sType, sKey) {
var data = null;
try {
data = JSON.parse(this.getStorage(sType).getItem(sKey));
}
catch (err) {
console.warn("invalid value for " + sKey);
}
return data;
};
WebStorageHelper.refresh = function (sType, sKey) {
if (!KeyStorageHelper.isManagedKey(sKey))
return;
var value = WebStorageHelper.retrieveFromStorage(sType, sKey);
if (value === null) {
delete CACHED[sType][sKey];
StorageObserverHelper.emit(sType, sKey, null);
}
else if (value !== CACHED[sType][sKey]) {
CACHED[sType][sKey] = value;
StorageObserverHelper.emit(sType, sKey, value);
}
};
WebStorageHelper.clearAll = function (sType) {
var storage = this.getStorage(sType);
KeyStorageHelper.retrieveKeysFromStorage(storage)
.forEach(function (sKey) {
storage.removeItem(sKey);
delete CACHED[sType][sKey];
StorageObserverHelper.emit(sType, sKey, null);
});
};
WebStorageHelper.clear = function (sType, sKey) {
this.getStorage(sType).removeItem(sKey);
delete CACHED[sType][sKey];
StorageObserverHelper.emit(sType, sKey, null);
};
WebStorageHelper.getStorage = function (sType) {
if (this.isStorageAvailable(sType))
return this.getWStorage(sType);
else
return MockStorageHelper.getStorage(sType);
};
WebStorageHelper.getWStorage = function (sType) {
var storage;
switch (sType) {
case STORAGE.local:
storage = localStorage;
break;
case STORAGE.session:
storage = sessionStorage;
break;
default:
throw Error('invalid storage type');
}
return storage;
};
WebStorageHelper.isStorageAvailable = function (sType) {
if (typeof STORAGEAVAILABILITY[sType] === 'boolean')
return STORAGEAVAILABILITY[sType];
var isAvailable = true, storage;
try {
storage = this.getWStorage(sType);
if (typeof storage === 'object') {
storage.setItem('test-storage', 'foobar');
storage.removeItem('test-storage');
}
else
isAvailable = false;
}
catch (e) {
isAvailable = false;
}
if (!isAvailable)
console.warn(STORAGE_NAMES[sType] + " storage unavailable, Ng2Webstorage will use a fallback strategy instead");
return STORAGEAVAILABILITY[sType] = isAvailable;
};
return WebStorageHelper;
}());
var _a$1;
var _b;
var WebStorageService = (function () {
function WebStorageService(sType) {
if (sType === void 0) { sType = null; }
this.sType = sType;
this.sType = sType;
}
WebStorageService.prototype.store = function (raw, value) {
var sKey = KeyStorageHelper.genKey(raw);
WebStorageHelper.store(this.sType, sKey, value);
};
WebStorageService.prototype.retrieve = function (raw) {
var sKey = KeyStorageHelper.genKey(raw);
return WebStorageHelper.retrieve(this.sType, sKey);
};
WebStorageService.prototype.clear = function (raw) {
if (raw)
WebStorageHelper.clear(this.sType, KeyStorageHelper.genKey(raw));
else
WebStorageHelper.clearAll(this.sType);
};
WebStorageService.prototype.observe = function (raw) {
var sKey = KeyStorageHelper.genKey(raw);
return StorageObserverHelper.observe(this.sType, sKey);
};
WebStorageService.prototype.isStorageAvailable = function () {
return WebStorageHelper.isStorageAvailable(this.sType);
};
return WebStorageService;
}());
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var LocalStorageService = (function (_super) {
__extends(LocalStorageService, _super);
function LocalStorageService() {
return _super.call(this, STORAGE.local) || this;
}
LocalStorageService.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
LocalStorageService.ctorParameters = function () { return []; };
return LocalStorageService;
}(WebStorageService));
var __extends$1 = (undefined && undefined.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var SessionStorageService = (function (_super) {
__extends$1(SessionStorageService, _super);
function SessionStorageService() {
return _super.call(this, STORAGE.session) || this;
}
SessionStorageService.decorators = [
{ type: _angular_core.Injectable },
];
/** @nocollapse */
SessionStorageService.ctorParameters = function () { return []; };
return SessionStorageService;
}(WebStorageService));
var WebstorageConfig = (function () {
function WebstorageConfig(config) {
this.prefix = LIB_KEY;
this.separator = LIB_KEY_SEPARATOR;
this.caseSensitive = LIB_KEY_CASE_SENSITIVE;
if (config && config.prefix !== undefined) {
this.prefix = config.prefix;
}
if (config && config.separator !== undefined) {
this.separator = config.separator;
}
if (config && config.caseSensitive !== undefined) {
this.caseSensitive = config.caseSensitive;
}
}
return WebstorageConfig;
}());
function WebStorage(webSKey, sType, defaultValue) {
if (defaultValue === void 0) { defaultValue = null; }
return function (targetedClass, raw) {
WebStorageDecorator(webSKey, sType, targetedClass, raw, defaultValue);
};
}
function WebStorageDecorator(webSKey, sType, targetedClass, raw, defaultValue) {
var key = webSKey || raw;
Object.defineProperty(targetedClass, raw, {
get: function () {
var sKey = KeyStorageHelper.genKey(key);
return WebStorageHelper.retrieve(sType, sKey);
},
set: function (value) {
var sKey = KeyStorageHelper.genKey(key);
this[sKey] = value;
WebStorageHelper.store(sType, sKey, value);
}
});
if (targetedClass[raw] === null && defaultValue !== undefined) {
var sub_1 = StorageObserverHelper.storageInit$.subscribe(function () {
targetedClass[raw] = defaultValue;
sub_1.unsubscribe();
});
}
}
function LocalStorage(webSKey, defaultValue) {
return function (targetedClass, raw) {
WebStorageDecorator(webSKey, STORAGE.local, targetedClass, raw, defaultValue);
};
}
function SessionStorage(webSKey, defaultValue) {
return function (targetedClass, raw) {
WebStorageDecorator(webSKey, STORAGE.session, targetedClass, raw, defaultValue);
};
}
var WEBSTORAGE_CONFIG = new _angular_core.InjectionToken('WEBSTORAGE_CONFIG');
var Ng2Webstorage = (function () {
function Ng2Webstorage(ngZone, config) {
this.ngZone = ngZone;
if (config) {
KeyStorageHelper.setStorageKeyPrefix(config.prefix);
KeyStorageHelper.setStorageKeySeparator(config.separator);
KeyStorageHelper.setCaseSensitivity(config.caseSensitive);
}
this.initStorageListener();
StorageObserverHelper.initStorage();
}
Ng2Webstorage.forRoot = function (config) {
return {
ngModule: Ng2Webstorage,
providers: [
{
provide: WEBSTORAGE_CONFIG,
useValue: config
},
{
provide: WebstorageConfig,
useFactory: provideConfig,
deps: [
WEBSTORAGE_CONFIG
]
}
]
};
};
Ng2Webstorage.prototype.initStorageListener = function () {
var _this = this;
if (typeof window !== 'undefined') {
window.addEventListener('storage', function (event) {
return _this.ngZone.run(function () {
var storage = window.sessionStorage === event.storageArea ? STORAGE.session : STORAGE.local;
WebStorageHelper.refresh(storage, event.key);
});
});
}
};
Ng2Webstorage.decorators = [
{ type: _angular_core.NgModule, args: [{
declarations: [],
providers: [SessionStorageService, LocalStorageService],
imports: []
},] },
];
/** @nocollapse */
Ng2Webstorage.ctorParameters = function () { return [
{ type: _angular_core.NgZone, },
{ type: WebstorageConfig, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Inject, args: [WebstorageConfig,] },] },
]; };
return Ng2Webstorage;
}());
function provideConfig(config) {
return new WebstorageConfig(config);
}
exports.WEBSTORAGE_CONFIG = WEBSTORAGE_CONFIG;
exports.Ng2Webstorage = Ng2Webstorage;
exports.provideConfig = provideConfig;
exports.WebstorageConfig = WebstorageConfig;
exports.LocalStorage = LocalStorage;
exports.SessionStorage = SessionStorage;
exports.WebStorage = WebStorage;
exports.WebStorageDecorator = WebStorageDecorator;
exports.WebStorageService = WebStorageService;
exports.LocalStorageService = LocalStorageService;
exports.SessionStorageService = SessionStorageService;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZS51bWQuanMiLCJzb3VyY2VzIjpbIi4uL2Rpc3QvZW51bXMvc3RvcmFnZS5qcyIsIi4uL2Rpc3QvY29uc3RhbnRzL2xpYi5qcyIsIi4uL2Rpc3QvaGVscGVycy9rZXlTdG9yYWdlLmpzIiwiLi4vZGlzdC9oZWxwZXJzL3N0b3JhZ2VPYnNlcnZlci5qcyIsIi4uL2Rpc3QvaGVscGVycy9tb2NrU3RvcmFnZS5qcyIsIi4uL2Rpc3QvaGVscGVycy93ZWJTdG9yYWdlLmpzIiwiLi4vZGlzdC9zZXJ2aWNlcy93ZWJTdG9yYWdlLmpzIiwiLi4vZGlzdC9zZXJ2aWNlcy9sb2NhbFN0b3JhZ2UuanMiLCIuLi9kaXN0L3NlcnZpY2VzL3Nlc3Npb25TdG9yYWdlLmpzIiwiLi4vZGlzdC9pbnRlcmZhY2VzL2NvbmZpZy5qcyIsIi4uL2Rpc3QvZGVjb3JhdG9ycy93ZWJTdG9yYWdlLmpzIiwiLi4vZGlzdC9kZWNvcmF0b3JzL2xvY2FsU3RvcmFnZS5qcyIsIi4uL2Rpc3QvZGVjb3JhdG9ycy9zZXNzaW9uU3RvcmFnZS5qcyIsIi4uL2Rpc3QvYXBwLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB2YXIgU1RPUkFHRTtcclxuKGZ1bmN0aW9uIChTVE9SQUdFKSB7XHJcbiAgICBTVE9SQUdFW1NUT1JBR0VbXCJsb2NhbFwiXSA9IDBdID0gXCJsb2NhbFwiO1xyXG4gICAgU1RPUkFHRVtTVE9SQUdFW1wic2Vzc2lvblwiXSA9IDFdID0gXCJzZXNzaW9uXCI7XHJcbn0pKFNUT1JBR0UgfHwgKFNUT1JBR0UgPSB7fSkpO1xyXG4vLyMgc291cmNlTWFwcGluZ1VSTD1zdG9yYWdlLmpzLm1hcCIsImltcG9ydCB7IFNUT1JBR0UgfSBmcm9tICcuLi9lbnVtcy9zdG9yYWdlJztcclxuZXhwb3J0IHZhciBMSUJfS0VZID0gJ25nMi13ZWJzdG9yYWdlJztcclxuZXhwb3J0IHZhciBMSUJfS0VZX1NFUEFSQVRPUiA9ICd8JztcclxuZXhwb3J0IHZhciBMSUJfS0VZX0NBU0VfU0VOU0lUSVZFID0gZmFsc2U7XHJcbmV4cG9ydCB2YXIgU1RPUkFHRV9OQU1FUyA9IChfYSA9IHt9LFxyXG4gICAgX2FbU1RPUkFHRS5sb2NhbF0gPSAnbG9jYWwnLFxyXG4gICAgX2FbU1RPUkFHRS5zZXNzaW9uXSA9ICdzZXNzaW9uJyxcclxuICAgIF9hKTtcclxudmFyIF9hO1xyXG4vLyMgc291cmNlTWFwcGluZ1VSTD1saWIuanMubWFwIiwiaW1wb3J0IHsgTElCX0tFWSwgTElCX0tFWV9DQVNFX1NFTlNJVElWRSwgTElCX0tFWV9TRVBBUkFUT1IgfSBmcm9tICcuLi9jb25zdGFudHMvbGliJztcclxudmFyIENVU1RPTV9MSUJfS0VZID0gTElCX0tFWTtcclxudmFyIENVU1RPTV9MSUJfS0VZX1NFUEFSQVRPUiA9IExJQl9LRVlfU0VQQVJBVE9SO1xyXG52YXIgQ1VTVE9NX0xJQl9LRVlfQ0FTRV9TRU5TSVRJVkUgPSBMSUJfS0VZX0NBU0VfU0VOU0lUSVZFO1xyXG5leHBvcnQgZnVuY3Rpb24gaXNNYW5hZ2VkS2V5KHNLZXkpIHtcclxuICAgIHJldHVybiBzS2V5LmluZGV4T2YoQ1VTVE9NX0xJQl9LRVkgKyBDVVNUT01fTElCX0tFWV9TRVBBUkFUT1IpID09PSAwO1xyXG59XHJcbnZhciBLZXlTdG9yYWdlSGVscGVyID0gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIEtleVN0b3JhZ2VIZWxwZXIoKSB7XHJcbiAgICB9XHJcbiAgICBLZXlTdG9yYWdlSGVscGVyLmlzTWFuYWdlZEtleSA9IGZ1bmN0aW9uIChzS2V5KSB7XHJcbiAgICAgICAgcmV0dXJuIHNLZXkuaW5kZXhPZihDVVNUT01fTElCX0tFWSArIENVU1RPTV9MSUJfS0VZX1NFUEFSQVRPUikgPT09IDA7XHJcbiAgICB9O1xyXG4gICAgS2V5U3RvcmFnZUhlbHBlci5yZXRyaWV2ZUtleXNGcm9tU3RvcmFnZSA9IGZ1bmN0aW9uIChzdG9yYWdlKSB7XHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHN0b3JhZ2UpLmZpbHRlcihpc01hbmFnZWRLZXkpO1xyXG4gICAgfTtcclxuICAgIEtleVN0b3JhZ2VIZWxwZXIuZ2VuS2V5ID0gZnVuY3Rpb24gKHJhdykge1xyXG4gICAgICAgIGlmICh0eXBlb2YgcmF3ICE9PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ2F0dGVtcHQgdG8gZ2VuZXJhdGUgYSBzdG9yYWdlIGtleSB3aXRoIGEgbm9uIHN0cmluZyB2YWx1ZScpO1xyXG4gICAgICAgIHJldHVybiBcIlwiICsgQ1VTVE9NX0xJQl9LRVkgKyBDVVNUT01fTElCX0tFWV9TRVBBUkFUT1IgKyB0aGlzLmZvcm1hdEtleShyYXcpO1xyXG4gICAgfTtcclxuICAgIEtleVN0b3JhZ2VIZWxwZXIuZm9ybWF0S2V5ID0gZnVuY3Rpb24gKHJhdykge1xyXG4gICAgICAgIHZhciBrZXkgPSByYXcudG9TdHJpbmcoKTtcclxuICAgICAgICByZXR1cm4gQ1VTVE9NX0xJQl9LRVlfQ0FTRV9TRU5TSVRJVkUgPyBrZXkgOiBrZXkudG9Mb3dlckNhc2UoKTtcclxuICAgIH07XHJcbiAgICBLZXlTdG9yYWdlSGVscGVyLnNldFN0b3JhZ2VLZXlQcmVmaXggPSBmdW5jdGlvbiAoa2V5KSB7XHJcbiAgICAgICAgaWYgKGtleSA9PT0gdm9pZCAwKSB7IGtleSA9IExJQl9LRVk7IH1cclxuICAgICAgICBDVVNUT01fTElCX0tFWSA9IGtleTtcclxuICAgIH07XHJcbiAgICBLZXlTdG9yYWdlSGVscGVyLnNldENhc2VTZW5zaXRpdml0eSA9IGZ1bmN0aW9uIChlbmFibGUpIHtcclxuICAgICAgICBpZiAoZW5hYmxlID09PSB2b2lkIDApIHsgZW5hYmxlID0gTElCX0tFWV9DQVNFX1NFTlNJVElWRTsgfVxyXG4gICAgICAgIENVU1RPTV9MSUJfS0VZX0NBU0VfU0VOU0lUSVZFID0gZW5hYmxlO1xyXG4gICAgfTtcclxuICAgIEtleVN0b3JhZ2VIZWxwZXIuc2V0U3RvcmFnZUtleVNlcGFyYXRvciA9IGZ1bmN0aW9uIChzZXBhcmF0b3IpIHtcclxuICAgICAgICBpZiAoc2VwYXJhdG9yID09PSB2b2lkIDApIHsgc2VwYXJhdG9yID0gTElCX0tFWV9TRVBBUkFUT1I7IH1cclxuICAgICAgICBDVVNUT01fTElCX0tFWV9TRVBBUkFUT1IgPSBzZXBhcmF0b3I7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIEtleVN0b3JhZ2VIZWxwZXI7XHJcbn0oKSk7XHJcbmV4cG9ydCB7IEtleVN0b3JhZ2VIZWxwZXIgfTtcclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9a2V5U3RvcmFnZS5qcy5tYXAiLCJpbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxudmFyIFN0b3JhZ2VPYnNlcnZlckhlbHBlciA9IChmdW5jdGlvbiAoKSB7XHJcbiAgICBmdW5jdGlvbiBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIoKSB7XHJcbiAgICB9XHJcbiAgICBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIub2JzZXJ2ZSA9IGZ1bmN0aW9uIChzVHlwZSwgc0tleSkge1xyXG4gICAgICAgIHZhciBvS2V5ID0gdGhpcy5nZW5PYnNlcnZlcktleShzVHlwZSwgc0tleSk7XHJcbiAgICAgICAgaWYgKG9LZXkgaW4gdGhpcy5vYnNlcnZlcnMpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9ic2VydmVyc1tvS2V5XTtcclxuICAgICAgICByZXR1cm4gdGhpcy5vYnNlcnZlcnNbb0tleV0gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgICB9O1xyXG4gICAgU3RvcmFnZU9ic2VydmVySGVscGVyLmVtaXQgPSBmdW5jdGlvbiAoc1R5cGUsIHNLZXksIHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIG9LZXkgPSB0aGlzLmdlbk9ic2VydmVyS2V5KHNUeXBlLCBzS2V5KTtcclxuICAgICAgICBpZiAob0tleSBpbiB0aGlzLm9ic2VydmVycylcclxuICAgICAgICAgICAgdGhpcy5vYnNlcnZlcnNbb0tleV0uZW1pdCh2YWx1ZSk7XHJcbiAgICB9O1xyXG4gICAgU3RvcmFnZU9ic2VydmVySGVscGVyLmdlbk9ic2VydmVyS2V5ID0gZnVuY3Rpb24gKHNUeXBlLCBzS2V5KSB7XHJcbiAgICAgICAgcmV0dXJuIHNUeXBlICsgJ3wnICsgc0tleTtcclxuICAgIH07XHJcbiAgICBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIuaW5pdFN0b3JhZ2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgU3RvcmFnZU9ic2VydmVySGVscGVyLnN0b3JhZ2VJbml0U3RyZWFtLmVtaXQodHJ1ZSk7XHJcbiAgICB9O1xyXG4gICAgU3RvcmFnZU9ic2VydmVySGVscGVyLm9ic2VydmVycyA9IHt9O1xyXG4gICAgU3RvcmFnZU9ic2VydmVySGVscGVyLnN0b3JhZ2VJbml0U3RyZWFtID0gbmV3IEV2ZW50RW1pdHRlcigpO1xyXG4gICAgU3RvcmFnZU9ic2VydmVySGVscGVyLnN0b3JhZ2VJbml0JCA9IFN0b3JhZ2VPYnNlcnZlckhlbHBlci5zdG9yYWdlSW5pdFN0cmVhbS5hc09ic2VydmFibGUoKTtcclxuICAgIHJldHVybiBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXI7XHJcbn0oKSk7XHJcbmV4cG9ydCB7IFN0b3JhZ2VPYnNlcnZlckhlbHBlciB9O1xyXG4vLyMgc291cmNlTWFwcGluZ1VSTD1zdG9yYWdlT2JzZXJ2ZXIuanMubWFwIiwidmFyIE1vY2tTdG9yYWdlSGVscGVyID0gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIE1vY2tTdG9yYWdlSGVscGVyKCkge1xyXG4gICAgfVxyXG4gICAgTW9ja1N0b3JhZ2VIZWxwZXIuaXNTZWN1cmVkRmllbGQgPSBmdW5jdGlvbiAoZmllbGQpIHtcclxuICAgICAgICByZXR1cm4gISF+TW9ja1N0b3JhZ2VIZWxwZXIuc2VjdXJlZEZpZWxkcy5pbmRleE9mKGZpZWxkKTtcclxuICAgIH07XHJcbiAgICBNb2NrU3RvcmFnZUhlbHBlci5nZXRTdG9yYWdlID0gZnVuY3Rpb24gKHNUeXBlKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLm1vY2tTdG9yYWdlc1tzVHlwZV0pXHJcbiAgICAgICAgICAgIHRoaXMubW9ja1N0b3JhZ2VzW3NUeXBlXSA9IE1vY2tTdG9yYWdlSGVscGVyLmdlbmVyYXRlU3RvcmFnZSgpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLm1vY2tTdG9yYWdlc1tzVHlwZV07XHJcbiAgICB9O1xyXG4gICAgTW9ja1N0b3JhZ2VIZWxwZXIuZ2VuZXJhdGVTdG9yYWdlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBzdG9yYWdlID0ge307XHJcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoc3RvcmFnZSwge1xyXG4gICAgICAgICAgICBzZXRJdGVtOiB7XHJcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB2YWx1ZTogZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIU1vY2tTdG9yYWdlSGVscGVyLmlzU2VjdXJlZEZpZWxkKGtleSkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5XSA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZ2V0SXRlbToge1xyXG4gICAgICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIChrZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gIU1vY2tTdG9yYWdlSGVscGVyLmlzU2VjdXJlZEZpZWxkKGtleSkgPyB0aGlzW2tleV0gfHwgbnVsbCA6IG51bGw7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICByZW1vdmVJdGVtOiB7XHJcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB2YWx1ZTogZnVuY3Rpb24gKGtleSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICghTW9ja1N0b3JhZ2VIZWxwZXIuaXNTZWN1cmVkRmllbGQoa2V5KSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXNba2V5XTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGxlbmd0aDoge1xyXG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMpLmxlbmd0aDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiBzdG9yYWdlO1xyXG4gICAgfTtcclxuICAgIE1vY2tTdG9yYWdlSGVscGVyLnNlY3VyZWRGaWVsZHMgPSBbJ3NldEl0ZW0nLCAnZ2V0SXRlbScsICdyZW1vdmVJdGVtJywgJ2xlbmd0aCddO1xyXG4gICAgTW9ja1N0b3JhZ2VIZWxwZXIubW9ja1N0b3JhZ2VzID0ge307XHJcbiAgICByZXR1cm4gTW9ja1N0b3JhZ2VIZWxwZXI7XHJcbn0oKSk7XHJcbmV4cG9ydCB7IE1vY2tTdG9yYWdlSGVscGVyIH07XHJcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1vY2tTdG9yYWdlLmpzLm1hcCIsImltcG9ydCB7IFNUT1JBR0UgfSBmcm9tICcuLi9lbnVtcy9zdG9yYWdlJztcclxuaW1wb3J0IHsgU3RvcmFnZU9ic2VydmVySGVscGVyIH0gZnJvbSAnLi9zdG9yYWdlT2JzZXJ2ZXInO1xyXG5pbXBvcnQgeyBLZXlTdG9yYWdlSGVscGVyIH0gZnJvbSAnLi9rZXlTdG9yYWdlJztcclxuaW1wb3J0IHsgTW9ja1N0b3JhZ2VIZWxwZXIgfSBmcm9tICcuL21vY2tTdG9yYWdlJztcclxuaW1wb3J0IHsgU1RPUkFHRV9OQU1FUyB9IGZyb20gJy4uL2NvbnN0YW50cy9saWInO1xyXG52YXIgQ0FDSEVEID0gKF9hID0ge30sIF9hW1NUT1JBR0UubG9jYWxdID0ge30sIF9hW1NUT1JBR0Uuc2Vzc2lvbl0gPSB7fSwgX2EpO1xyXG52YXIgU1RPUkFHRUFWQUlMQUJJTElUWSA9IChfYiA9IHt9LCBfYltTVE9SQUdFLmxvY2FsXSA9IG51bGwsIF9iW1NUT1JBR0Uuc2Vzc2lvbl0gPSBudWxsLCBfYik7XHJcbnZhciBXZWJTdG9yYWdlSGVscGVyID0gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIFdlYlN0b3JhZ2VIZWxwZXIoKSB7XHJcbiAgICB9XHJcbiAgICBXZWJTdG9yYWdlSGVscGVyLnN0b3JlID0gZnVuY3Rpb24gKHNUeXBlLCBzS2V5LCB2YWx1ZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0U3RvcmFnZShzVHlwZSkuc2V0SXRlbShzS2V5LCBKU09OLnN0cmluZ2lmeSh2YWx1ZSkpO1xyXG4gICAgICAgIENBQ0hFRFtzVHlwZV1bc0tleV0gPSB2YWx1ZTtcclxuICAgICAgICBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIuZW1pdChzVHlwZSwgc0tleSwgdmFsdWUpO1xyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VIZWxwZXIucmV0cmlldmUgPSBmdW5jdGlvbiAoc1R5cGUsIHNLZXkpIHtcclxuICAgICAgICBpZiAoQ0FDSEVEW3NUeXBlXVtzS2V5XSlcclxuICAgICAgICAgICAgcmV0dXJuIENBQ0hFRFtzVHlwZV1bc0tleV07XHJcbiAgICAgICAgcmV0dXJuIENBQ0hFRFtzVHlwZV1bc0tleV0gPSBXZWJTdG9yYWdlSGVscGVyLnJldHJpZXZlRnJvbVN0b3JhZ2Uoc1R5cGUsIHNLZXkpO1xyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VIZWxwZXIucmV0cmlldmVGcm9tU3RvcmFnZSA9IGZ1bmN0aW9uIChzVHlwZSwgc0tleSkge1xyXG4gICAgICAgIHZhciBkYXRhID0gbnVsbDtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBkYXRhID0gSlNPTi5wYXJzZSh0aGlzLmdldFN0b3JhZ2Uoc1R5cGUpLmdldEl0ZW0oc0tleSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcImludmFsaWQgdmFsdWUgZm9yIFwiICsgc0tleSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBkYXRhO1xyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VIZWxwZXIucmVmcmVzaCA9IGZ1bmN0aW9uIChzVHlwZSwgc0tleSkge1xyXG4gICAgICAgIGlmICghS2V5U3RvcmFnZUhlbHBlci5pc01hbmFnZWRLZXkoc0tleSkpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB2YXIgdmFsdWUgPSBXZWJTdG9yYWdlSGVscGVyLnJldHJpZXZlRnJvbVN0b3JhZ2Uoc1R5cGUsIHNLZXkpO1xyXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICBkZWxldGUgQ0FDSEVEW3NUeXBlXVtzS2V5XTtcclxuICAgICAgICAgICAgU3RvcmFnZU9ic2VydmVySGVscGVyLmVtaXQoc1R5cGUsIHNLZXksIG51bGwpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh2YWx1ZSAhPT0gQ0FDSEVEW3NUeXBlXVtzS2V5XSkge1xyXG4gICAgICAgICAgICBDQUNIRURbc1R5cGVdW3NLZXldID0gdmFsdWU7XHJcbiAgICAgICAgICAgIFN0b3JhZ2VPYnNlcnZlckhlbHBlci5lbWl0KHNUeXBlLCBzS2V5LCB2YWx1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VIZWxwZXIuY2xlYXJBbGwgPSBmdW5jdGlvbiAoc1R5cGUpIHtcclxuICAgICAgICB2YXIgc3RvcmFnZSA9IHRoaXMuZ2V0U3RvcmFnZShzVHlwZSk7XHJcbiAgICAgICAgS2V5U3RvcmFnZUhlbHBlci5yZXRyaWV2ZUtleXNGcm9tU3RvcmFnZShzdG9yYWdlKVxyXG4gICAgICAgICAgICAuZm9yRWFjaChmdW5jdGlvbiAoc0tleSkge1xyXG4gICAgICAgICAgICBzdG9yYWdlLnJlbW92ZUl0ZW0oc0tleSk7XHJcbiAgICAgICAgICAgIGRlbGV0ZSBDQUNIRURbc1R5cGVdW3NLZXldO1xyXG4gICAgICAgICAgICBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIuZW1pdChzVHlwZSwgc0tleSwgbnVsbCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9O1xyXG4gICAgV2ViU3RvcmFnZUhlbHBlci5jbGVhciA9IGZ1bmN0aW9uIChzVHlwZSwgc0tleSkge1xyXG4gICAgICAgIHRoaXMuZ2V0U3RvcmFnZShzVHlwZSkucmVtb3ZlSXRlbShzS2V5KTtcclxuICAgICAgICBkZWxldGUgQ0FDSEVEW3NUeXBlXVtzS2V5XTtcclxuICAgICAgICBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIuZW1pdChzVHlwZSwgc0tleSwgbnVsbCk7XHJcbiAgICB9O1xyXG4gICAgV2ViU3RvcmFnZUhlbHBlci5nZXRTdG9yYWdlID0gZnVuY3Rpb24gKHNUeXBlKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNTdG9yYWdlQXZhaWxhYmxlKHNUeXBlKSlcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0V1N0b3JhZ2Uoc1R5cGUpO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgcmV0dXJuIE1vY2tTdG9yYWdlSGVscGVyLmdldFN0b3JhZ2Uoc1R5cGUpO1xyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VIZWxwZXIuZ2V0V1N0b3JhZ2UgPSBmdW5jdGlvbiAoc1R5cGUpIHtcclxuICAgICAgICB2YXIgc3RvcmFnZTtcclxuICAgICAgICBzd2l0Y2ggKHNUeXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgU1RPUkFHRS5sb2NhbDpcclxuICAgICAgICAgICAgICAgIHN0b3JhZ2UgPSBsb2NhbFN0b3JhZ2U7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBTVE9SQUdFLnNlc3Npb246XHJcbiAgICAgICAgICAgICAgICBzdG9yYWdlID0gc2Vzc2lvblN0b3JhZ2U7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCdpbnZhbGlkIHN0b3JhZ2UgdHlwZScpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gc3RvcmFnZTtcclxuICAgIH07XHJcbiAgICBXZWJTdG9yYWdlSGVscGVyLmlzU3RvcmFnZUF2YWlsYWJsZSA9IGZ1bmN0aW9uIChzVHlwZSkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgU1RPUkFHRUFWQUlMQUJJTElUWVtzVHlwZV0gPT09ICdib29sZWFuJylcclxuICAgICAgICAgICAgcmV0dXJuIFNUT1JBR0VBVkFJTEFCSUxJVFlbc1R5cGVdO1xyXG4gICAgICAgIHZhciBpc0F2YWlsYWJsZSA9IHRydWUsIHN0b3JhZ2U7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgc3RvcmFnZSA9IHRoaXMuZ2V0V1N0b3JhZ2Uoc1R5cGUpO1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHN0b3JhZ2UgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgICAgICBzdG9yYWdlLnNldEl0ZW0oJ3Rlc3Qtc3RvcmFnZScsICdmb29iYXInKTtcclxuICAgICAgICAgICAgICAgIHN0b3JhZ2UucmVtb3ZlSXRlbSgndGVzdC1zdG9yYWdlJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgaXNBdmFpbGFibGUgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgaXNBdmFpbGFibGUgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCFpc0F2YWlsYWJsZSlcclxuICAgICAgICAgICAgY29uc29sZS53YXJuKFNUT1JBR0VfTkFNRVNbc1R5cGVdICsgXCIgc3RvcmFnZSB1bmF2YWlsYWJsZSwgTmcyV2Vic3RvcmFnZSB3aWxsIHVzZSBhIGZhbGxiYWNrIHN0cmF0ZWd5IGluc3RlYWRcIik7XHJcbiAgICAgICAgcmV0dXJuIFNUT1JBR0VBVkFJTEFCSUxJVFlbc1R5cGVdID0gaXNBdmFpbGFibGU7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIFdlYlN0b3JhZ2VIZWxwZXI7XHJcbn0oKSk7XHJcbmV4cG9ydCB7IFdlYlN0b3JhZ2VIZWxwZXIgfTtcclxudmFyIF9hLCBfYjtcclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9d2ViU3RvcmFnZS5qcy5tYXAiLCJpbXBvcnQgeyBLZXlTdG9yYWdlSGVscGVyLCBXZWJTdG9yYWdlSGVscGVyLCBTdG9yYWdlT2JzZXJ2ZXJIZWxwZXIgfSBmcm9tICcuLi9oZWxwZXJzL2luZGV4JztcclxudmFyIFdlYlN0b3JhZ2VTZXJ2aWNlID0gKGZ1bmN0aW9uICgpIHtcclxuICAgIGZ1bmN0aW9uIFdlYlN0b3JhZ2VTZXJ2aWNlKHNUeXBlKSB7XHJcbiAgICAgICAgaWYgKHNUeXBlID09PSB2b2lkIDApIHsgc1R5cGUgPSBudWxsOyB9XHJcbiAgICAgICAgdGhpcy5zVHlwZSA9IHNUeXBlO1xyXG4gICAgICAgIHRoaXMuc1R5cGUgPSBzVHlwZTtcclxuICAgIH1cclxuICAgIFdlYlN0b3JhZ2VTZXJ2aWNlLnByb3RvdHlwZS5zdG9yZSA9IGZ1bmN0aW9uIChyYXcsIHZhbHVlKSB7XHJcbiAgICAgICAgdmFyIHNLZXkgPSBLZXlTdG9yYWdlSGVscGVyLmdlbktleShyYXcpO1xyXG4gICAgICAgIFdlYlN0b3JhZ2VIZWxwZXIuc3RvcmUodGhpcy5zVHlwZSwgc0tleSwgdmFsdWUpO1xyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VTZXJ2aWNlLnByb3RvdHlwZS5yZXRyaWV2ZSA9IGZ1bmN0aW9uIChyYXcpIHtcclxuICAgICAgICB2YXIgc0tleSA9IEtleVN0b3JhZ2VIZWxwZXIuZ2VuS2V5KHJhdyk7XHJcbiAgICAgICAgcmV0dXJuIFdlYlN0b3JhZ2VIZWxwZXIucmV0cmlldmUodGhpcy5zVHlwZSwgc0tleSk7XHJcbiAgICB9O1xyXG4gICAgV2ViU3RvcmFnZVNlcnZpY2UucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKHJhdykge1xyXG4gICAgICAgIGlmIChyYXcpXHJcbiAgICAgICAgICAgIFdlYlN0b3JhZ2VIZWxwZXIuY2xlYXIodGhpcy5zVHlwZSwgS2V5U3RvcmFnZUhlbHBlci5nZW5LZXkocmF3KSk7XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICBXZWJTdG9yYWdlSGVscGVyLmNsZWFyQWxsKHRoaXMuc1R5cGUpO1xyXG4gICAgfTtcclxuICAgIFdlYlN0b3JhZ2VTZXJ2aWNlLnByb3RvdHlwZS5vYnNlcnZlID0gZnVuY3Rpb24gKHJhdykge1xyXG4gICAgICAgIHZhciBzS2V5ID0gS2V5U3RvcmFnZUhlbHBlci5nZW5LZXkocmF3KTtcclxuICAgICAgICByZXR1cm4gU3RvcmFnZU9ic2VydmVySGVscGVyLm9ic2VydmUodGhpcy5zVHlwZSwgc0tleSk7XHJcbiAgICB9O1xyXG4gICAgV2ViU3RvcmFnZVNlcnZpY2UucHJvdG90eXBlLmlzU3RvcmFnZUF2YWlsYWJsZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gV2ViU3RvcmFnZUhlbHBlci5pc1N0b3JhZ2VBdmFpbGFibGUodGhpcy5zVHlwZSk7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIFdlYlN0b3JhZ2VTZXJ2aWNlO1xyXG59KCkpO1xyXG5leHBvcnQgeyBXZWJTdG9yYWdlU2VydmljZSB9O1xyXG4vLyMgc291cmNlTWFwcGluZ1VSTD13ZWJTdG9yYWdlLmpzLm1hcCIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcclxuICAgIHZhciBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XHJcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbiAgICB9O1xyXG59KSgpO1xyXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFNUT1JBR0UgfSBmcm9tICcuLi9lbnVtcy9zdG9yYWdlJztcclxuaW1wb3J0IHsgV2ViU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuL3dlYlN0b3JhZ2UnO1xyXG52YXIgTG9jYWxTdG9yYWdlU2VydmljZSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XHJcbiAgICBfX2V4dGVuZHMoTG9jYWxTdG9yYWdlU2VydmljZSwgX3N1cGVyKTtcclxuICAgIGZ1bmN0aW9uIExvY2FsU3RvcmFnZVNlcnZpY2UoKSB7XHJcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIFNUT1JBR0UubG9jYWwpIHx8IHRoaXM7XHJcbiAgICB9XHJcbiAgICBMb2NhbFN0b3JhZ2VTZXJ2aWNlLmRlY29yYXRvcnMgPSBbXHJcbiAgICAgICAgeyB0eXBlOiBJbmplY3RhYmxlIH0sXHJcbiAgICBdO1xyXG4gICAgLyoqIEBub2NvbGxhcHNlICovXHJcbiAgICBMb2NhbFN0b3JhZ2VTZXJ2aWNlLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH07XHJcbiAgICByZXR1cm4gTG9jYWxTdG9yYWdlU2VydmljZTtcclxufShXZWJTdG9yYWdlU2VydmljZSkpO1xyXG5leHBvcnQgeyBMb2NhbFN0b3JhZ2VTZXJ2aWNlIH07XHJcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxvY2FsU3RvcmFnZS5qcy5tYXAiLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xyXG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG4gICAgfTtcclxufSkoKTtcclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBTVE9SQUdFIH0gZnJvbSAnLi4vZW51bXMvc3RvcmFnZSc7XHJcbmltcG9ydCB7IFdlYlN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnLi93ZWJTdG9yYWdlJztcclxudmFyIFNlc3Npb25TdG9yYWdlU2VydmljZSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XHJcbiAgICBfX2V4dGVuZHMoU2Vzc2lvblN0b3JhZ2VTZXJ2aWNlLCBfc3VwZXIpO1xyXG4gICAgZnVuY3Rpb24gU2Vzc2lvblN0b3JhZ2VTZXJ2aWNlKCkge1xyXG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBTVE9SQUdFLnNlc3Npb24pIHx8IHRoaXM7XHJcbiAgICB9XHJcbiAgICBTZXNzaW9uU3RvcmFnZVNlcnZpY2UuZGVjb3JhdG9ycyA9IFtcclxuICAgICAgICB7IHR5cGU6IEluamVjdGFibGUgfSxcclxuICAgIF07XHJcbiAgICAvKiogQG5vY29sbGFwc2UgKi9cclxuICAgIFNlc3Npb25TdG9yYWdlU2VydmljZS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtdOyB9O1xyXG4gICAgcmV0dXJuIFNlc3Npb25TdG9yYWdlU2VydmljZTtcclxufShXZWJTdG9yYWdlU2VydmljZSkpO1xyXG5leHBvcnQgeyBTZXNzaW9uU3RvcmFnZVNlcnZpY2UgfTtcclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2Vzc2lvblN0b3JhZ2UuanMubWFwIiwiaW1wb3J0IHsgTElCX0tFWSwgTElCX0tFWV9DQVNFX1NFTlNJVElWRSwgTElCX0tFWV9TRVBBUkFUT1IgfSBmcm9tICcuLi9jb25zdGFudHMvbGliJztcclxudmFyIFdlYnN0b3JhZ2VDb25maWcgPSAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gV2Vic3RvcmFnZUNvbmZpZyhjb25maWcpIHtcclxuICAgICAgICB0aGlzLnByZWZpeCA9IExJQl9LRVk7XHJcbiAgICAgICAgdGhpcy5zZXBhcmF0b3IgPSBMSUJfS0VZX1NFUEFSQVRPUjtcclxuICAgICAgICB0aGlzLmNhc2VTZW5zaXRpdmUgPSBMSUJfS0VZX0NBU0VfU0VOU0lUSVZFO1xyXG4gICAgICAgIGlmIChjb25maWcgJiYgY29uZmlnLnByZWZpeCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMucHJlZml4ID0gY29uZmlnLnByZWZpeDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGNvbmZpZyAmJiBjb25maWcuc2VwYXJhdG9yICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5zZXBhcmF0b3IgPSBjb25maWcuc2VwYXJhdG9yO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29uZmlnICYmIGNvbmZpZy5jYXNlU2Vuc2l0aXZlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5jYXNlU2Vuc2l0aXZlID0gY29uZmlnLmNhc2VTZW5zaXRpdmU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIFdlYnN0b3JhZ2VDb25maWc7XHJcbn0oKSk7XHJcbmV4cG9ydCB7IFdlYnN0b3JhZ2VDb25maWcgfTtcclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29uZmlnLmpzLm1hcCIsImltcG9ydCB7IEtleVN0b3JhZ2VIZWxwZXIsIFdlYlN0b3JhZ2VIZWxwZXIgfSBmcm9tICcuLi9oZWxwZXJzL2luZGV4JztcclxuaW1wb3J0IHsgU3RvcmFnZU9ic2VydmVySGVscGVyIH0gZnJvbSAnLi4vaGVscGVycy9zdG9yYWdlT2JzZXJ2ZXInO1xyXG5leHBvcnQgZnVuY3Rpb24gV2ViU3RvcmFnZSh3ZWJTS2V5LCBzVHlwZSwgZGVmYXVsdFZhbHVlKSB7XHJcbiAgICBpZiAoZGVmYXVsdFZhbHVlID09PSB2b2lkIDApIHsgZGVmYXVsdFZhbHVlID0gbnVsbDsgfVxyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXRlZENsYXNzLCByYXcpIHtcclxuICAgICAgICBXZWJTdG9yYWdlRGVjb3JhdG9yKHdlYlNLZXksIHNUeXBlLCB0YXJnZXRlZENsYXNzLCByYXcsIGRlZmF1bHRWYWx1ZSk7XHJcbiAgICB9O1xyXG59XHJcbmV4cG9ydCBmdW5jdGlvbiBXZWJTdG9yYWdlRGVjb3JhdG9yKHdlYlNLZXksIHNUeXBlLCB0YXJnZXRlZENsYXNzLCByYXcsIGRlZmF1bHRWYWx1ZSkge1xyXG4gICAgdmFyIGtleSA9IHdlYlNLZXkgfHwgcmF3O1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldGVkQ2xhc3MsIHJhdywge1xyXG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgc0tleSA9IEtleVN0b3JhZ2VIZWxwZXIuZ2VuS2V5KGtleSk7XHJcbiAgICAgICAgICAgIHJldHVybiBXZWJTdG9yYWdlSGVscGVyLnJldHJpZXZlKHNUeXBlLCBzS2V5KTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHZhciBzS2V5ID0gS2V5U3RvcmFnZUhlbHBlci5nZW5LZXkoa2V5KTtcclxuICAgICAgICAgICAgdGhpc1tzS2V5XSA9IHZhbHVlO1xyXG4gICAgICAgICAgICBXZWJTdG9yYWdlSGVscGVyLnN0b3JlKHNUeXBlLCBzS2V5LCB2YWx1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICBpZiAodGFyZ2V0ZWRDbGFzc1tyYXddID09PSBudWxsICYmIGRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdmFyIHN1Yl8xID0gU3RvcmFnZU9ic2VydmVySGVscGVyLnN0b3JhZ2VJbml0JC5zdWJzY3JpYmUoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB0YXJnZXRlZENsYXNzW3Jhd10gPSBkZWZhdWx0VmFsdWU7XHJcbiAgICAgICAgICAgIHN1Yl8xLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9d2ViU3RvcmFnZS5qcy5tYXAiLCJpbXBvcnQgeyBXZWJTdG9yYWdlRGVjb3JhdG9yIH0gZnJvbSAnLi93ZWJTdG9yYWdlJztcclxuaW1wb3J0IHsgU1RPUkFHRSB9IGZyb20gJy4uL2VudW1zL3N0b3JhZ2UnO1xyXG5leHBvcnQgZnVuY3Rpb24gTG9jYWxTdG9yYWdlKHdlYlNLZXksIGRlZmF1bHRWYWx1ZSkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXRlZENsYXNzLCByYXcpIHtcclxuICAgICAgICBXZWJTdG9yYWdlRGVjb3JhdG9yKHdlYlNLZXksIFNUT1JBR0UubG9jYWwsIHRhcmdldGVkQ2xhc3MsIHJhdywgZGVmYXVsdFZhbHVlKTtcclxuICAgIH07XHJcbn1cclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bG9jYWxTdG9yYWdlLmpzLm1hcCIsImltcG9ydCB7IFdlYlN0b3JhZ2VEZWNvcmF0b3IgfSBmcm9tICcuL3dlYlN0b3JhZ2UnO1xyXG5pbXBvcnQgeyBTVE9SQUdFIH0gZnJvbSAnLi4vZW51bXMvc3RvcmFnZSc7XHJcbmV4cG9ydCBmdW5jdGlvbiBTZXNzaW9uU3RvcmFnZSh3ZWJTS2V5LCBkZWZhdWx0VmFsdWUpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0ZWRDbGFzcywgcmF3KSB7XHJcbiAgICAgICAgV2ViU3RvcmFnZURlY29yYXRvcih3ZWJTS2V5LCBTVE9SQUdFLnNlc3Npb24sIHRhcmdldGVkQ2xhc3MsIHJhdywgZGVmYXVsdFZhbHVlKTtcclxuICAgIH07XHJcbn1cclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2Vzc2lvblN0b3JhZ2UuanMubWFwIiwiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3Rpb25Ub2tlbiwgTmdNb2R1bGUsIE5nWm9uZSwgT3B0aW9uYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU1RPUkFHRSB9IGZyb20gJy4vZW51bXMvc3RvcmFnZSc7XHJcbmltcG9ydCB7IExvY2FsU3RvcmFnZVNlcnZpY2UsIFNlc3Npb25TdG9yYWdlU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvaW5kZXgnO1xyXG5pbXBvcnQgeyBXZWJTdG9yYWdlSGVscGVyIH0gZnJvbSAnLi9oZWxwZXJzL3dlYlN0b3JhZ2UnO1xyXG5pbXBvcnQgeyBXZWJzdG9yYWdlQ29uZmlnIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2NvbmZpZyc7XHJcbmltcG9ydCB7IEtleVN0b3JhZ2VIZWxwZXIgfSBmcm9tICcuL2hlbHBlcnMva2V5U3RvcmFnZSc7XHJcbmltcG9ydCB7IFN0b3JhZ2VPYnNlcnZlckhlbHBlciB9IGZyb20gJy4vaGVscGVycy9zdG9yYWdlT2JzZXJ2ZXInO1xyXG5leHBvcnQgKiBmcm9tICcuL2ludGVyZmFjZXMvaW5kZXgnO1xyXG5leHBvcnQgKiBmcm9tICcuL2RlY29yYXRvcnMvaW5kZXgnO1xyXG5leHBvcnQgKiBmcm9tICcuL3NlcnZpY2VzL2luZGV4JztcclxuZXhwb3J0IHZhciBXRUJTVE9SQUdFX0NPTkZJRyA9IG5ldyBJbmplY3Rpb25Ub2tlbignV0VCU1RPUkFHRV9DT05GSUcnKTtcclxudmFyIE5nMldlYnN0b3JhZ2UgPSAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gTmcyV2Vic3RvcmFnZShuZ1pvbmUsIGNvbmZpZykge1xyXG4gICAgICAgIHRoaXMubmdab25lID0gbmdab25lO1xyXG4gICAgICAgIGlmIChjb25maWcpIHtcclxuICAgICAgICAgICAgS2V5U3RvcmFnZUhlbHBlci5zZXRTdG9yYWdlS2V5UHJlZml4KGNvbmZpZy5wcmVmaXgpO1xyXG4gICAgICAgICAgICBLZXlTdG9yYWdlSGVscGVyLnNldFN0b3JhZ2VLZXlTZXBhcmF0b3IoY29uZmlnLnNlcGFyYXRvcik7XHJcbiAgICAgICAgICAgIEtleVN0b3JhZ2VIZWxwZXIuc2V0Q2FzZVNlbnNpdGl2aXR5KGNvbmZpZy5jYXNlU2Vuc2l0aXZlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5pbml0U3RvcmFnZUxpc3RlbmVyKCk7XHJcbiAgICAgICAgU3RvcmFnZU9ic2VydmVySGVscGVyLmluaXRTdG9yYWdlKCk7XHJcbiAgICB9XHJcbiAgICBOZzJXZWJzdG9yYWdlLmZvclJvb3QgPSBmdW5jdGlvbiAoY29uZmlnKSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgbmdNb2R1bGU6IE5nMldlYnN0b3JhZ2UsXHJcbiAgICAgICAgICAgIHByb3ZpZGVyczogW1xyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGU6IFdFQlNUT1JBR0VfQ09ORklHLFxyXG4gICAgICAgICAgICAgICAgICAgIHVzZVZhbHVlOiBjb25maWdcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZTogV2Vic3RvcmFnZUNvbmZpZyxcclxuICAgICAgICAgICAgICAgICAgICB1c2VGYWN0b3J5OiBwcm92aWRlQ29uZmlnLFxyXG4gICAgICAgICAgICAgICAgICAgIGRlcHM6IFtcclxuICAgICAgICAgICAgICAgICAgICAgICAgV0VCU1RPUkFHRV9DT05GSUdcclxuICAgICAgICAgICAgICAgICAgICBdXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIF1cclxuICAgICAgICB9O1xyXG4gICAgfTtcclxuICAgIE5nMldlYnN0b3JhZ2UucHJvdG90eXBlLmluaXRTdG9yYWdlTGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcclxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3N0b3JhZ2UnLCBmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5uZ1pvbmUucnVuKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgc3RvcmFnZSA9IHdpbmRvdy5zZXNzaW9uU3RvcmFnZSA9PT0gZXZlbnQuc3RvcmFnZUFyZWEgPyBTVE9SQUdFLnNlc3Npb24gOiBTVE9SQUdFLmxvY2FsO1xyXG4gICAgICAgICAgICAgICAgICAgIFdlYlN0b3JhZ2VIZWxwZXIucmVmcmVzaChzdG9yYWdlLCBldmVudC5rZXkpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICBOZzJXZWJzdG9yYWdlLmRlY29yYXRvcnMgPSBbXHJcbiAgICAgICAgeyB0eXBlOiBOZ01vZHVsZSwgYXJnczogW3tcclxuICAgICAgICAgICAgICAgICAgICBkZWNsYXJhdGlvbnM6IFtdLFxyXG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW1Nlc3Npb25TdG9yYWdlU2VydmljZSwgTG9jYWxTdG9yYWdlU2VydmljZV0sXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0czogW11cclxuICAgICAgICAgICAgICAgIH0sXSB9LFxyXG4gICAgXTtcclxuICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xyXG4gICAgTmcyV2Vic3RvcmFnZS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtcclxuICAgICAgICB7IHR5cGU6IE5nWm9uZSwgfSxcclxuICAgICAgICB7IHR5cGU6IFdlYnN0b3JhZ2VDb25maWcsIGRlY29yYXRvcnM6IFt7IHR5cGU6IE9wdGlvbmFsIH0sIHsgdHlwZTogSW5qZWN0LCBhcmdzOiBbV2Vic3RvcmFnZUNvbmZpZyxdIH0sXSB9LFxyXG4gICAgXTsgfTtcclxuICAgIHJldHVybiBOZzJXZWJzdG9yYWdlO1xyXG59KCkpO1xyXG5leHBvcnQgeyBOZzJXZWJzdG9yYWdlIH07XHJcbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlQ29uZmlnKGNvbmZpZykge1xyXG4gICAgcmV0dXJuIG5ldyBXZWJzdG9yYWdlQ29uZmlnKGNvbmZpZyk7XHJcbn1cclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9YXBwLmpzLm1hcCJdLCJuYW1lcyI6WyJFdmVudEVtaXR0ZXIiLCJfYSIsInRoaXMiLCJJbmplY3RhYmxlIiwiX19leHRlbmRzIiwiSW5qZWN0aW9uVG9rZW4iLCJOZ01vZHVsZSIsIk5nWm9uZSIsIk9wdGlvbmFsIiwiSW5qZWN0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBTyxJQUFJLE9BQU8sQ0FBQztBQUNuQixDQUFDLFVBQVUsT0FBTyxFQUFFO0lBQ2hCLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDO0lBQ3hDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDO0NBQy9DLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxBQUM5Qjs7QUNKTyxJQUFJLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztBQUN0QyxBQUFPLElBQUksaUJBQWlCLEdBQUcsR0FBRyxDQUFDO0FBQ25DLEFBQU8sSUFBSSxzQkFBc0IsR0FBRyxLQUFLLENBQUM7QUFDMUMsQUFBTyxJQUFJLGFBQWEsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFO0lBQy9CLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTztJQUMzQixFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLFNBQVM7SUFDL0IsRUFBRSxDQUFDLENBQUM7QUFDUixJQUFJLEVBQUUsQ0FBQyxBQUNQOztBQ1JBLElBQUksY0FBYyxHQUFHLE9BQU8sQ0FBQztBQUM3QixJQUFJLHdCQUF3QixHQUFHLGlCQUFpQixDQUFDO0FBQ2pELElBQUksNkJB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